diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 79b7c8b3b..000a814bd 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -23,9 +23,11 @@ The SDK's primary artifacts are:
- Does not have its own logic
- `openai-java-bedrock`
- Adds optional Amazon Bedrock authentication and credential-provider integration
-- `openai-java-spring-boot-starter`
- - Provides the legacy Spring Boot 2 integration
- - Is retained to verify the final 4.45.0 release, but is OpenAI EOL and no longer published
+
+The retired Spring Boot 2 starter is not part of the active build. Its final source remains available
+in the [`v4.45.0` tag](https://github.com/openai/openai-java/tree/v4.45.0/openai-java-spring-boot-starter),
+and its lifecycle history and consumer migration path are documented in the
+[Spring Boot 2 EOL decision](docs/spring-boot-2-eol.md).
`openai-java-runtime-compatibility` is a non-published fixture that exercises representative
behavior for each supported artifact on an isolated runtime classpath. Its JVM matrix and each
diff --git a/README.md b/README.md
index 7d26dd4d5..92a2c5cad 100644
--- a/README.md
+++ b/README.md
@@ -1455,79 +1455,15 @@ GraalVM should automatically detect and use the published metadata, but [manual
> [!WARNING]
> `openai-java-spring-boot-starter` targets Spring Boot 2.7 and is OpenAI EOL as of 2026-07-27.
> Version 4.45.0 is the final supported, tested, and published release. The artifact remains
-> downloadable but receives no fixes, testing, or compatibility support. See the
+> downloadable but receives no fixes, testing, or compatibility support, and its source is no
+> longer part of the active build. See the
> [Spring Boot 2 EOL decision and migration path](docs/spring-boot-2-eol.md). New Spring
> applications should depend on `openai-java` directly and provide an `OpenAIClient` bean until a
> supported, generation-specific integration is available.
-Existing Spring Boot 2 applications can use the legacy starter to simplify configuration.
-
-### Installation
-
-#### Gradle
-
-```kotlin
-implementation("com.openai:openai-java-spring-boot-starter:4.45.0")
-```
-
-#### Maven
-
-```xml
-
- com.openai
- openai-java-spring-boot-starter
- 4.45.0
-
-```
-
-### Configuration
-
-The [client's environment variable options](#client-configuration) can be configured in [`application.properties` or `application.yml`](https://docs.spring.io/spring-boot/how-to/properties-and-configuration.html).
-
-#### `application.properties`
-
-```properties
-openai.base-url=https://api.openai.com/v1
-openai.api-key=My API Key
-openai.admin-key=My Admin API Key
-openai.org-id=My Organization
-openai.project-id=My Project
-openai.webhook-secret=My Webhook Secret
-```
-
-#### `application.yml`
-
-```yaml
-openai:
- base-url: https://api.openai.com/v1
- api-key: My API Key
- admin-key: My Admin API Key
- org-id: My Organization
- project-id: My Project
- webhook-secret: My Webhook Secret
-```
-
-#### Other configuration
-
-Configure any other client option by providing one or more instances of [`OpenAIClientCustomizer`](openai-java-spring-boot-starter/src/main/kotlin/com/openai/springboot/OpenAIClientCustomizer.kt). For example, here's how you'd set [`maxRetries`](#retries):
-
-```java
-import com.openai.springboot.OpenAIClientCustomizer;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-@Configuration
-public class OpenAIConfig {
- @Bean
- public OpenAIClientCustomizer customizer() {
- return builder -> builder.maxRetries(3);
- }
-}
-```
-
-### Usage
-
-[Inject](https://docs.spring.io/spring-framework/reference/core/beans/dependencies/factory-collaborators.html) [`OpenAIClient`](openai-java-core/src/main/kotlin/com/openai/client/OpenAIClient.kt) anywhere and start using it!
+Existing Spring Boot 2 users can refer to the
+[`v4.45.0` Spring Boot documentation](https://github.com/openai/openai-java/blob/v4.45.0/README.md#spring-boot)
+for the final legacy configuration and usage instructions.
## Jackson
diff --git a/docs/spring-boot-2-eol.md b/docs/spring-boot-2-eol.md
index 6b3325a6b..e319bb73c 100644
--- a/docs/spring-boot-2-eol.md
+++ b/docs/spring-boot-2-eol.md
@@ -20,6 +20,27 @@ floor, or changing the same coordinate to a newer Spring generation would requir
A future supported Spring integration must use generation-specific coordinates and independently
pass the policy's 12-month admission gate.
+## History and source removal
+
+The starter was introduced in SDK 2.18.0 after
+[an external request](https://github.com/openai/openai-java/issues/480) for Spring Boot
+`application.properties` and `application.yml` support. It was a customer-facing convenience
+artifact, not a test fixture: it bound `openai.*` configuration, created an injectable
+`OpenAIClient` bean, and allowed applications to customize the client builder.
+
+The starter's source was removed from the active build after its final release. Keeping that source
+on the default branch did not verify 4.45.0: the module depended on the current checkout's
+`openai-java` project and therefore compiled and tested an unpublished, changing combination of the
+current SDK with Spring Boot 2.7.18. It also kept the EOL Spring dependency graph active for
+repository security scanning.
+
+Removing the active source does not withdraw the released artifact. Version 4.45.0 remains on Maven
+Central, and its exact implementation and tests remain available in the
+[`v4.45.0` source tag](https://github.com/openai/openai-java/tree/v4.45.0/openai-java-spring-boot-starter).
+The tagged
+[`v4.45.0` README](https://github.com/openai/openai-java/blob/v4.45.0/README.md#spring-boot)
+preserves its final installation and configuration instructions.
+
## Consumer migration
Applications that cannot leave Boot 2 may pin the starter to 4.45.0, but do so without OpenAI or
diff --git a/docs/version-support-policy.md b/docs/version-support-policy.md
index fc17644f1..1640df974 100644
--- a/docs/version-support-policy.md
+++ b/docs/version-support-policy.md
@@ -66,7 +66,7 @@ that apply this policy.
| Surface | Decision | Next action |
| --- | --- | --- |
| Framework-neutral artifacts | Keep Java 8 through SDK v4. | Raise the floor only in an SDK major; first prefer replacing or isolating a constraining dependency. |
-| Existing Spring Boot 2 starter | OpenAI EOL as of 2026-07-27; 4.45.0 is the final supported and published release. | Follow the [Spring Boot 2 EOL decision](spring-boot-2-eol.md); publish no later versions. |
+| Retired Spring Boot 2 starter | OpenAI EOL as of 2026-07-27; 4.45.0 is the final supported and published release, and its source is no longer in the active build. | Keep the final artifact and tagged source available; follow the [Spring Boot 2 EOL decision](spring-boot-2-eol.md); publish no later versions. |
| Potential Spring Boot 4 integration | Candidate Java 17 integration using a new generation-specific artifact. | Pass the admission gate and Spring ADR before implementation. |
Do not publish an OpenAI Java BOM until independently versioned artifacts or demonstrated consumer
diff --git a/gradle/version-support.properties b/gradle/version-support.properties
index 4c55d7516..ce6cec66c 100644
--- a/gradle/version-support.properties
+++ b/gradle/version-support.properties
@@ -15,5 +15,3 @@ artifact.openai-java-client-okhttp.runtime=8
artifact.openai-java-client-okhttp.lifecycle=active
artifact.openai-java-core.runtime=8
artifact.openai-java-core.lifecycle=active
-artifact.openai-java-spring-boot-starter.runtime=8
-artifact.openai-java-spring-boot-starter.lifecycle=eol
diff --git a/openai-java-spring-boot-starter/build.gradle.kts b/openai-java-spring-boot-starter/build.gradle.kts
deleted file mode 100644
index 6b68e7ecb..000000000
--- a/openai-java-spring-boot-starter/build.gradle.kts
+++ /dev/null
@@ -1,40 +0,0 @@
-plugins {
- id("openai.kotlin")
-}
-
-repositories {
- mavenCentral()
-}
-
-dependencies {
- constraints {
- testImplementation("org.xmlunit:xmlunit-core:2.11.0") {
- because("2.11.0 includes the fix for CVE-2024-31573 in this test-only dependency")
- }
- testImplementation("com.jayway.jsonpath:json-path:2.10.0") {
- because("Spring Boot's transitive JSONPath version has a stack-overflow vulnerability")
- }
- testImplementation("org.slf4j:slf4j-api") {
- version { strictly("1.7.36") }
- because("Spring Boot 2.7 requires SLF4J 1.7 at test runtime")
- }
- }
-
- api(project(":openai-java"))
- implementation("org.springframework.boot:spring-boot-autoconfigure:2.7.18")
- annotationProcessor("org.springframework.boot:spring-boot-configuration-processor:2.7.18")
-
- testImplementation("org.springframework.boot:spring-boot-starter-test:2.7.18") {
- exclude(group = "org.springframework.boot", module = "spring-boot-starter-logging")
- }
- testRuntimeOnly("org.slf4j:slf4j-nop:1.7.36") {
- because("keep Boot 2.7 tests on SLF4J 1.7 without adding vulnerable Logback")
- }
- testImplementation("org.assertj:assertj-core:3.27.7")
-
- constraints {
- testImplementation("org.yaml:snakeyaml:2.6") {
- because("avoid known vulnerabilities in Spring Boot's test dependency")
- }
- }
-}
diff --git a/openai-java-spring-boot-starter/src/main/kotlin/com/openai/springboot/OpenAIClientAutoConfiguration.kt b/openai-java-spring-boot-starter/src/main/kotlin/com/openai/springboot/OpenAIClientAutoConfiguration.kt
deleted file mode 100644
index dd6c55af9..000000000
--- a/openai-java-spring-boot-starter/src/main/kotlin/com/openai/springboot/OpenAIClientAutoConfiguration.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-// File generated from our OpenAPI spec by Stainless.
-
-package com.openai.springboot
-
-import com.openai.client.OpenAIClient
-import com.openai.client.okhttp.OpenAIOkHttpClient
-import org.springframework.beans.factory.ObjectProvider
-import org.springframework.boot.autoconfigure.AutoConfiguration
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
-import org.springframework.boot.context.properties.EnableConfigurationProperties
-import org.springframework.context.annotation.Bean
-
-@AutoConfiguration
-@ConditionalOnClass(OpenAIClient::class)
-@EnableConfigurationProperties(OpenAIClientProperties::class)
-class OpenAIClientAutoConfiguration {
-
- @Bean
- @ConditionalOnMissingBean
- internal fun client(
- properties: OpenAIClientProperties,
- customizers: ObjectProvider,
- ): OpenAIClient =
- OpenAIOkHttpClient.builder()
- .apply {
- properties.baseUrl?.let { baseUrl(it) }
- properties.apiKey?.let { apiKey(it) }
- properties.adminApiKey?.let { adminApiKey(it) }
- properties.organization?.let { organization(it) }
- properties.project?.let { project(it) }
- properties.webhookSecret?.let { webhookSecret(it) }
- customizers.orderedStream().forEach { it.customize(this) }
- }
- .build()
-}
diff --git a/openai-java-spring-boot-starter/src/main/kotlin/com/openai/springboot/OpenAIClientCustomizer.kt b/openai-java-spring-boot-starter/src/main/kotlin/com/openai/springboot/OpenAIClientCustomizer.kt
deleted file mode 100644
index b86c4b7d7..000000000
--- a/openai-java-spring-boot-starter/src/main/kotlin/com/openai/springboot/OpenAIClientCustomizer.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-// File generated from our OpenAPI spec by Stainless.
-
-package com.openai.springboot
-
-import com.openai.client.okhttp.OpenAIOkHttpClient
-
-fun interface OpenAIClientCustomizer {
-
- fun customize(builder: OpenAIOkHttpClient.Builder)
-}
diff --git a/openai-java-spring-boot-starter/src/main/kotlin/com/openai/springboot/OpenAIClientProperties.kt b/openai-java-spring-boot-starter/src/main/kotlin/com/openai/springboot/OpenAIClientProperties.kt
deleted file mode 100644
index 443b8a8bc..000000000
--- a/openai-java-spring-boot-starter/src/main/kotlin/com/openai/springboot/OpenAIClientProperties.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-// File generated from our OpenAPI spec by Stainless.
-
-package com.openai.springboot
-
-import org.springframework.boot.context.properties.ConfigurationProperties
-import org.springframework.boot.context.properties.ConstructorBinding
-import org.springframework.boot.context.properties.bind.Name
-
-@ConfigurationProperties(prefix = "openai")
-internal data class OpenAIClientProperties
-@ConstructorBinding
-constructor(
- @Name("base-url") val baseUrl: String? = null,
- @Name("api-key") val apiKey: String? = null,
- @Name("admin-key") val adminApiKey: String? = null,
- @Name("org-id") val organization: String? = null,
- @Name("project-id") val project: String? = null,
- @Name("webhook-secret") val webhookSecret: String? = null,
-)
diff --git a/openai-java-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/openai-java-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json
deleted file mode 100644
index 7875f417f..000000000
--- a/openai-java-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
- "properties": [
- {
- "name": "openai.base-url",
- "type": "java.lang.String",
- "defaultValue": "https://api.openai.com/v1",
- "sourceType": "com.openai.springboot.OpenAIClientProperties"
- },
- {
- "name": "openai.api-key",
- "type": "java.lang.String",
- "sourceType": "com.openai.springboot.OpenAIClientProperties"
- },
- {
- "name": "openai.admin-key",
- "type": "java.lang.String",
- "sourceType": "com.openai.springboot.OpenAIClientProperties"
- },
- {
- "name": "openai.org-id",
- "type": "java.lang.String",
- "sourceType": "com.openai.springboot.OpenAIClientProperties"
- },
- {
- "name": "openai.project-id",
- "type": "java.lang.String",
- "sourceType": "com.openai.springboot.OpenAIClientProperties"
- },
- {
- "name": "openai.webhook-secret",
- "type": "java.lang.String",
- "sourceType": "com.openai.springboot.OpenAIClientProperties"
- }
- ]
-}
\ No newline at end of file
diff --git a/openai-java-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/openai-java-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
deleted file mode 100644
index d1d2e241e..000000000
--- a/openai-java-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ /dev/null
@@ -1 +0,0 @@
-com.openai.springboot.OpenAIClientAutoConfiguration
\ No newline at end of file
diff --git a/openai-java-spring-boot-starter/src/test/kotlin/com/openai/springboot/OpenAIClientAutoConfigurationTest.kt b/openai-java-spring-boot-starter/src/test/kotlin/com/openai/springboot/OpenAIClientAutoConfigurationTest.kt
deleted file mode 100644
index c9b386667..000000000
--- a/openai-java-spring-boot-starter/src/test/kotlin/com/openai/springboot/OpenAIClientAutoConfigurationTest.kt
+++ /dev/null
@@ -1,108 +0,0 @@
-// File generated from our OpenAPI spec by Stainless.
-
-package com.openai.springboot
-
-import com.openai.client.OpenAIClient
-import java.nio.charset.StandardCharsets
-import org.assertj.core.api.Assertions.assertThat
-import org.junit.jupiter.api.Test
-import org.springframework.beans.factory.getBean
-import org.springframework.boot.autoconfigure.AutoConfigurations
-import org.springframework.boot.env.YamlPropertySourceLoader
-import org.springframework.boot.test.context.runner.ApplicationContextRunner
-import org.springframework.core.io.ByteArrayResource
-
-internal class OpenAIClientAutoConfigurationTest {
-
- private val contextRunner =
- ApplicationContextRunner()
- .withConfiguration(AutoConfigurations.of(OpenAIClientAutoConfiguration::class.java))
-
- @Test
- fun properties() {
- contextRunner
- .withPropertyValues(
- "openai.base-url=https://api.openai.com/v1",
- "openai.api-key=My API Key",
- "openai.admin-key=My Admin API Key",
- "openai.org-id=My Organization",
- "openai.project-id=My Project",
- "openai.webhook-secret=My Webhook Secret",
- )
- .run { context ->
- val properties = context.getBean()
- assertThat(properties.baseUrl).isEqualTo("https://api.openai.com/v1")
- assertThat(properties.apiKey).isEqualTo("My API Key")
- assertThat(properties.adminApiKey).isEqualTo("My Admin API Key")
- assertThat(properties.organization).isEqualTo("My Organization")
- assertThat(properties.project).isEqualTo("My Project")
- assertThat(properties.webhookSecret).isEqualTo("My Webhook Secret")
- }
- }
-
- @Test
- fun yamlProperties() {
- val resource =
- ByteArrayResource(
- """
- openai:
- base-url: https://api.openai.com/v1
- api-key: YAML API Key
- org-id: YAML Organization
- """
- .trimIndent()
- .toByteArray(StandardCharsets.UTF_8)
- )
- val propertySources = YamlPropertySourceLoader().load("test", resource)
-
- contextRunner
- .withInitializer { context ->
- propertySources.reversed().forEach {
- context.environment.propertySources.addFirst(it)
- }
- }
- .run { context ->
- val properties = context.getBean()
- assertThat(properties.baseUrl).isEqualTo("https://api.openai.com/v1")
- assertThat(properties.apiKey).isEqualTo("YAML API Key")
- assertThat(properties.organization).isEqualTo("YAML Organization")
- context.getBean()
- }
- }
-
- @Test
- fun client() {
- contextRunner
- .withPropertyValues(
- "openai.base-url=https://api.openai.com/v1",
- "openai.api-key=My API Key",
- "openai.admin-key=My Admin API Key",
- "openai.org-id=My Organization",
- "openai.project-id=My Project",
- "openai.webhook-secret=My Webhook Secret",
- )
- .run { it.getBean() }
- }
-
- @Test
- fun clientWithCustomizers() {
- var customized = false
- contextRunner
- .withPropertyValues(
- "openai.base-url=https://api.openai.com/v1",
- "openai.api-key=My API Key",
- "openai.admin-key=My Admin API Key",
- "openai.org-id=My Organization",
- "openai.project-id=My Project",
- "openai.webhook-secret=My Webhook Secret",
- )
- .withBean(
- OpenAIClientCustomizer::class.java,
- { OpenAIClientCustomizer { customized = true } },
- )
- .run {
- it.getBean()
- assertThat(customized).isTrue()
- }
- }
-}
diff --git a/openai-java-spring-boot-starter/src/test/kotlin/com/openai/springboot/SpringBootLoggingCompatibilityTest.kt b/openai-java-spring-boot-starter/src/test/kotlin/com/openai/springboot/SpringBootLoggingCompatibilityTest.kt
deleted file mode 100644
index 5f69aa5e8..000000000
--- a/openai-java-spring-boot-starter/src/test/kotlin/com/openai/springboot/SpringBootLoggingCompatibilityTest.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-// File generated from our OpenAPI spec by Stainless.
-
-package com.openai.springboot
-
-import com.openai.client.OpenAIClient
-import org.assertj.core.api.Assertions.assertThat
-import org.junit.jupiter.api.Test
-import org.springframework.boot.SpringBootConfiguration
-import org.springframework.boot.WebApplicationType
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration
-import org.springframework.boot.builder.SpringApplicationBuilder
-
-internal class SpringBootLoggingCompatibilityTest {
-
- @Test
- fun springApplicationStartsWithoutLogback() {
- val classLoader = Thread.currentThread().contextClassLoader ?: javaClass.classLoader
- assertThat(classLoader.getResource("ch/qos/logback/core/Context.class")).isNull()
- assertThat(classLoader.getResource("ch/qos/logback/classic/Logger.class")).isNull()
-
- SpringApplicationBuilder(TestApplication::class.java)
- .web(WebApplicationType.NONE)
- .properties("openai.api-key=test")
- .run()
- .use { context -> assertThat(context.getBean(OpenAIClient::class.java)).isNotNull() }
- }
-
- @SpringBootConfiguration @EnableAutoConfiguration internal open class TestApplication
-}