java/index.md +136 −6
2 2
3<!-- x-release-please-start-version -->3<!-- x-release-please-start-version -->
4 4
55[](https://central.sonatype.com/artifact/com.openai/openai-java/4.48.0)[](https://central.sonatype.com/artifact/com.openai/openai-java/4.49.0)
66[](https://javadoc.io/doc/com.openai/openai-java/4.48.0)[](https://javadoc.io/doc/com.openai/openai-java/4.49.0)
7 7
8<!-- x-release-please-end -->8<!-- x-release-please-end -->
9 9
11 11
12<!-- x-release-please-start-version -->12<!-- x-release-please-start-version -->
13 13
1414The 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.48.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.49.0).
15 15
16<!-- x-release-please-end -->16<!-- x-release-please-end -->
17 17
22### Gradle22### Gradle
23 23
24```kotlin24```kotlin
2525implementation("com.openai:openai-java:4.48.0")implementation("com.openai:openai-java:4.49.0")
26```26```
27 27
28### Maven28### Maven
31<dependency>31<dependency>
32 <groupId>com.openai</groupId>32 <groupId>com.openai</groupId>
33 <artifactId>openai-java</artifactId>33 <artifactId>openai-java</artifactId>
3434 <version>4.48.0</version> <version>4.49.0</version>
35</dependency>35</dependency>
36```36```
37 37
94<!-- x-release-please-start-version -->94<!-- x-release-please-start-version -->
95 95
96```kotlin96```kotlin
9797implementation("com.openai:openai-java-bedrock:4.48.0")implementation("com.openai:openai-java-bedrock:4.49.0")
98```98```
99 99
100<!-- x-release-please-end -->100<!-- x-release-please-end -->
1696 .build();1696 .build();
1697```1697```
1698 1698
1699#### Mutual TLS with native JSSE
1700
1701API-key authenticated HTTP requests can use mTLS without a dedicated SDK API. Build an
1702`SSLContext` using Java's native JSSE APIs and pass it through the existing OkHttp TLS hooks.
1703
1704To opt in, follow the
1705[OpenAI Mutual TLS Beta Program](https://help.openai.com/en/articles/10876024-openai-mutual-tls-beta-program)
1706guide to upload a CA certificate and activate it for your project or organization before
1707configuring the client.
1708
1709Certificate-chain support is a separate mTLS beta capability that is available by request. Contact
1710your Account Director or OpenAI Support to enable it. When it is enabled, the PKCS#12 key store must
1711contain the client private key and the complete certificate chain: the leaf certificate first,
1712followed by every required intermediate certificate. Without certificate-chain support, the client
1713leaf certificate must be directly signed by an active CA certificate that you uploaded to OpenAI.
1714
1715Keep server trust separate from the client identity. Initializing `TrustManagerFactory` with a null
1716`KeyStore` retains the JVM's normal server-trust configuration.
1717
1718```java
1719import com.openai.client.OpenAIClient;
1720import com.openai.client.okhttp.OpenAIOkHttpClient;
1721import java.io.InputStream;
1722import java.net.URI;
1723import java.nio.file.Files;
1724import java.nio.file.Paths;
1725import java.security.KeyStore;
1726import java.util.Arrays;
1727import javax.net.ssl.KeyManagerFactory;
1728import javax.net.ssl.SSLContext;
1729import javax.net.ssl.TrustManager;
1730import javax.net.ssl.TrustManagerFactory;
1731import javax.net.ssl.X509TrustManager;
1732
1733String apiKey = System.getProperty("openai.apiKey");
1734if (apiKey == null) {
1735 apiKey = System.getenv("OPENAI_API_KEY");
1736}
1737if (apiKey == null || apiKey.isEmpty()) {
1738 throw new IllegalStateException(
1739 "openai.apiKey or OPENAI_API_KEY must be set for OpenAI mTLS");
1740}
1741String baseUrl = System.getProperty("openai.baseUrl");
1742if (baseUrl == null) {
1743 baseUrl = System.getenv("OPENAI_BASE_URL");
1744}
1745if (baseUrl == null) {
1746 baseUrl = "https://mtls.api.openai.com/v1";
1747} else if (baseUrl.isEmpty()) {
1748 throw new IllegalStateException(
1749 "openai.baseUrl or OPENAI_BASE_URL must not be empty for OpenAI mTLS");
1750}
1751URI baseUri;
1752try {
1753 baseUri = URI.create(baseUrl);
1754} catch (IllegalArgumentException ignored) {
1755 // URI parse exceptions include the rejected value, which may contain credentials.
1756 throw new IllegalStateException("OpenAI mTLS requires a valid HTTPS base URL");
1757}
1758if (!"https".equalsIgnoreCase(baseUri.getScheme()) || baseUri.getRawAuthority() == null) {
1759 throw new IllegalStateException("OpenAI mTLS requires a valid HTTPS base URL");
1760}
1761String organization = System.getProperty("openai.orgId");
1762if (organization == null) {
1763 organization = System.getenv("OPENAI_ORG_ID");
1764}
1765String project = System.getProperty("openai.projectId");
1766if (project == null) {
1767 project = System.getenv("OPENAI_PROJECT_ID");
1768}
1769
1770String keyStorePath = System.getenv("OPENAI_MTLS_KEYSTORE");
1771String keyStorePassword = System.getenv("OPENAI_MTLS_KEYSTORE_PASSWORD");
1772if (keyStorePath == null || keyStorePath.isEmpty()) {
1773 throw new IllegalStateException("OPENAI_MTLS_KEYSTORE must be set");
1774}
1775if (keyStorePassword == null || keyStorePassword.isEmpty()) {
1776 throw new IllegalStateException("OPENAI_MTLS_KEYSTORE_PASSWORD must be set");
1777}
1778
1779char[] password = keyStorePassword.toCharArray();
1780KeyStore clientKeyStore = KeyStore.getInstance("PKCS12");
1781KeyManagerFactory keyManagers =
1782 KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
1783try {
1784 try (InputStream input = Files.newInputStream(Paths.get(keyStorePath))) {
1785 clientKeyStore.load(input, password);
1786 }
1787 keyManagers.init(clientKeyStore, password);
1788} finally {
1789 Arrays.fill(password, '\0');
1790}
1791
1792TrustManagerFactory trustManagers =
1793 TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
1794trustManagers.init((KeyStore) null);
1795X509TrustManager trustManager = Arrays.stream(trustManagers.getTrustManagers())
1796 .filter(X509TrustManager.class::isInstance)
1797 .map(X509TrustManager.class::cast)
1798 .findFirst()
1799 .orElseThrow(() -> new IllegalStateException(
1800 "The default TrustManagerFactory did not provide an X509TrustManager"));
1801
1802SSLContext sslContext = SSLContext.getInstance("TLS");
1803sslContext.init(keyManagers.getKeyManagers(), new TrustManager[] {trustManager}, null);
1804
1805OpenAIClient client = OpenAIOkHttpClient.builder()
1806 // Set the OpenAI credential explicitly so an Azure key cannot be selected accidentally.
1807 .apiKey(apiKey)
1808 // Preserve the organization and project scope selected by normal SDK configuration.
1809 .organization(organization)
1810 .project(project)
1811 .baseUrl(baseUrl)
1812 // Avoid presenting the client identity to a redirect target.
1813 .followRedirects(false)
1814 .sslSocketFactory(sslContext.getSocketFactory())
1815 .trustManager(trustManager)
1816 .build();
1817```
1818
1819Set `openai.baseUrl` or `OPENAI_BASE_URL` to `https://mtls-eu.api.openai.com/v1` for EU Data
1820Residency, or to an appropriate custom mTLS gateway. If neither is set, the recipe uses
1821`https://mtls.api.openai.com/v1`. The SDK does not inspect or rewrite that URL. To rotate the client
1822identity, build a new `SSLContext`, HTTP transport, and SDK client, then close the old client. This
1823recipe applies to ordinary HTTP API-key traffic; it does not add certificate-only authentication or
1824Realtime/WebSocket mTLS support.
1825
1826See the complete, compilable
1827[`MutualTlsExample`](openai-java-example/src/main/java/com/openai/example/MutualTlsExample.java).
1828
1699### Custom HTTP client1829### Custom HTTP client
1700 1830
1701The SDK consists of three artifacts:1831The SDK consists of three artifacts: