The Anthropic Java SDK provides convenient access to the Anthropic REST API from applications written in Java
This document covers how to create, configure, and customize the Anthropic Java client for different deployment scenarios.
The SDK provides factory methods through AnthropicOkHttpClient for creating client instances.
package com.anthropic.client.okhttp;
public class AnthropicOkHttpClient {
// Create from environment variables and system properties
@JvmStatic
public static AnthropicClient fromEnv();
// Create builder for manual configuration
@JvmStatic
public static Builder builder();
}Environment-based creation (recommended):
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
// Reads ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN, ANTHROPIC_BASE_URL
// Or anthropic.apiKey, anthropic.authToken, anthropic.baseUrl system properties
AnthropicClient client = AnthropicOkHttpClient.fromEnv();Manual configuration:
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
AnthropicClient client = AnthropicOkHttpClient.builder()
.apiKey("my-anthropic-api-key")
.build();Hybrid approach (environment + overrides):
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
AnthropicClient client = AnthropicOkHttpClient.builder()
.fromEnv() // Load defaults from environment
.apiKey("my-anthropic-api-key") // Override specific values
.build();The SDK supports multiple authentication mechanisms with flexible configuration.
public class AnthropicOkHttpClient.Builder {
// Set API key for authentication
public Builder apiKey(String apiKey);
// Set auth token for authentication
public Builder authToken(String authToken);
}Environment Variables:
| Environment Variable | Description |
|---|---|
ANTHROPIC_API_KEY | Your Anthropic API key |
ANTHROPIC_AUTH_TOKEN | Alternative authentication token |
ANTHROPIC_BASE_URL | Custom API base URL (default: https://api.anthropic.com) |
System Properties:
| System Property | Description |
|---|---|
anthropic.apiKey | Your Anthropic API key |
anthropic.authToken | Alternative authentication token |
anthropic.baseUrl | Custom API base URL |
Priority: System properties take precedence over environment variables.
Example with explicit credentials:
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
AnthropicClient client = AnthropicOkHttpClient.builder()
.apiKey(System.getenv("MY_CUSTOM_API_KEY"))
.baseUrl("https://custom-api.example.com")
.build();The AnthropicOkHttpClient.Builder provides comprehensive configuration methods.
public class AnthropicOkHttpClient.Builder {
// Load configuration from environment
public Builder fromEnv();
// Authentication
public Builder apiKey(String apiKey);
public Builder authToken(String authToken);
// Base URL configuration
public Builder baseUrl(String baseUrl);
// Network settings
public Builder timeout(Duration timeout);
public Builder maxRetries(int maxRetries);
// Custom headers and query parameters
public Builder headers(Map<String, Iterable<String>> headers);
public Builder queryParams(Map<String, Iterable<String>> queryParams);
// JSON serialization
public Builder jsonMapper(JsonMapper jsonMapper);
// HTTP client customization (advanced)
public Builder proxy(Proxy proxy);
public Builder sslSocketFactory(SSLSocketFactory factory);
public Builder trustManager(X509TrustManager manager);
public Builder hostnameVerifier(HostnameVerifier verifier);
// Platform backends
public Builder backend(Backend backend);
// Build the client
public AnthropicClient build();
}Configure request timeouts globally or per-request:
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import java.time.Duration;
// Set default timeout for all requests
AnthropicClient client = AnthropicOkHttpClient.builder()
.fromEnv()
.timeout(Duration.ofSeconds(30))
.build();Default timeout behavior:
maxTokens values (non-streaming): Dynamic timeout up to 60 minutes calculated as:
min(3600 seconds, max(600 seconds, 3600 * maxTokens / 128000))Configure automatic retry behavior:
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
// Set maximum retry attempts (default: 2)
AnthropicClient client = AnthropicOkHttpClient.builder()
.fromEnv()
.maxRetries(4)
.build();Retryable errors:
Add custom headers or query parameters to all requests:
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import java.util.Map;
import java.util.List;
AnthropicClient client = AnthropicOkHttpClient.builder()
.fromEnv()
.headers(Map.of(
"X-Custom-Header", List.of("value1", "value2")
))
.queryParams(Map.of(
"custom_param", List.of("value")
))
.build();Configure individual requests with RequestOptions to override client defaults.
package com.anthropic.core;
public class RequestOptions {
public static Builder builder();
public static class Builder {
// Override timeout for this request
public Builder timeout(Duration timeout);
// Enable response validation for this request
public Builder responseValidation(boolean validation);
// Add custom headers
public Builder putHeader(String name, String value);
// Add custom query parameters
public Builder putQueryParam(String key, String value);
public RequestOptions build();
}
}import com.anthropic.core.RequestOptions;
import com.anthropic.models.messages.Message;
import com.anthropic.models.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;
import java.time.Duration;
MessageCreateParams params = MessageCreateParams.builder()
.maxTokens(1024L)
.addUserMessage("Hello, Claude")
.model(Model.CLAUDE_SONNET_4_5)
.build();
// Override timeout for this specific request
RequestOptions options = RequestOptions.builder()
.timeout(Duration.ofSeconds(60))
.responseValidation(true)
.build();
Message message = client.messages().create(params, options);The SDK provides both synchronous and asynchronous client variants.
package com.anthropic.client;
public interface AnthropicClient {
// Convert sync client to async
AnthropicClientAsync async();
}
public interface AnthropicClientAsync {
// Convert async client to sync
AnthropicClient sync();
}Create async client from sync:
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.AnthropicClientAsync;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import com.anthropic.models.messages.Message;
import com.anthropic.models.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;
import java.util.concurrent.CompletableFuture;
AnthropicClient syncClient = AnthropicOkHttpClient.fromEnv();
AnthropicClientAsync asyncClient = syncClient.async();
MessageCreateParams params = MessageCreateParams.builder()
.maxTokens(1024L)
.addUserMessage("Hello, Claude")
.model(Model.CLAUDE_SONNET_4_5)
.build();
CompletableFuture<Message> future = asyncClient.messages().create(params);Create async client directly:
import com.anthropic.client.AnthropicClientAsync;
import com.anthropic.client.okhttp.AnthropicOkHttpClientAsync;
import com.anthropic.models.messages.Message;
import java.util.concurrent.CompletableFuture;
AnthropicClientAsync client = AnthropicOkHttpClientAsync.fromEnv();
CompletableFuture<Message> future = client.messages().create(params);Configure thread pool for async streaming operations:
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
// Configure global executor for stream handlers
Executor executor = Executors.newFixedThreadPool(4);
AnthropicClient client = AnthropicOkHttpClient.builder()
.fromEnv()
.streamHandlerExecutor(executor)
.build();Per-request executor override:
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
Executor customExecutor = Executors.newFixedThreadPool(2);
client.async().messages().createStreaming(params).subscribe(
chunk -> System.out.println(chunk),
customExecutor
);Create modified client instances while reusing connection pools and resources.
package com.anthropic.client;
public interface AnthropicClient {
// Create modified client with new options
AnthropicClient withOptions(Consumer<ClientOptions.Builder> modifier);
}
public interface AnthropicClientAsync {
// Create modified async client with new options
AnthropicClientAsync withOptions(Consumer<ClientOptions.Builder> modifier);
}Example usage:
import com.anthropic.client.AnthropicClient;
// Create modified client without affecting the original
AnthropicClient modifiedClient = client.withOptions(optionsBuilder -> {
optionsBuilder.baseUrl("https://example.com");
optionsBuilder.maxRetries(5);
optionsBuilder.timeout(Duration.ofMinutes(2));
});
// Original client is unchanged
// modifiedClient uses new configuration but shares connection poolpackage com.anthropic.core;
public class ClientOptions.Builder {
// HTTP client implementation
public Builder httpClient(HttpClient httpClient);
// JSON configuration
public Builder jsonMapper(JsonMapper jsonMapper);
public Builder checkJacksonVersionCompatibility(boolean check);
// Async streaming
public Builder streamHandlerExecutor(Executor executor);
// Timing and delays
public Builder sleeper(Sleeper sleeper);
public Builder clock(Clock clock);
// Base configuration
public Builder baseUrl(String baseUrl);
public Builder timeout(Duration timeout);
public Builder maxRetries(int maxRetries);
// Validation
public Builder responseValidation(boolean validation);
// Headers and query parameters
public Builder putHeader(String name, String value);
public Builder putQueryParam(String key, String value);
public ClientOptions build();
}Advanced network configuration for proxies, HTTPS, and custom HTTP clients.
Route requests through a proxy server:
public class AnthropicOkHttpClient.Builder {
public Builder proxy(Proxy proxy);
}Example:
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import java.net.InetSocketAddress;
import java.net.Proxy;
AnthropicClient client = AnthropicOkHttpClient.builder()
.fromEnv()
.proxy(new Proxy(
Proxy.Type.HTTP,
new InetSocketAddress("proxy.example.com", 8080)
))
.build();Customize SSL/TLS settings for HTTPS connections:
public class AnthropicOkHttpClient.Builder {
public Builder sslSocketFactory(SSLSocketFactory factory);
public Builder trustManager(X509TrustManager manager);
public Builder hostnameVerifier(HostnameVerifier verifier);
}Example with custom SSL:
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.net.ssl.HostnameVerifier;
// Custom SSL configuration (use with caution)
AnthropicClient client = AnthropicOkHttpClient.builder()
.fromEnv()
.sslSocketFactory(customSSLSocketFactory)
.trustManager(customTrustManager)
.hostnameVerifier(customHostnameVerifier)
.build();Note: Most applications should use system defaults. Custom SSL configuration may reduce security optimizations.
Exponential backoff: Automatic exponential backoff between retry attempts with jitter.
Timeout calculation for large responses:
For non-streaming requests with large maxTokens:
timeout = min(3600, max(600, 3600 * maxTokens / 128000)) secondsmaxTokens valueLong-running requests: For requests expected to take longer than 10 minutes, use streaming or explicitly override the timeout.
Configure alternative API backends for cloud platforms:
public class AnthropicOkHttpClient.Builder {
public Builder backend(Backend backend);
}AWS Bedrock:
import com.anthropic.bedrock.backends.BedrockBackend;
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
AnthropicClient client = AnthropicOkHttpClient.builder()
.backend(BedrockBackend.fromEnv())
.build();Google Vertex AI:
import com.anthropic.vertex.backends.VertexBackend;
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
AnthropicClient client = AnthropicOkHttpClient.builder()
.backend(VertexBackend.fromEnv())
.build();Important: Create one client per application and reuse it across requests. Each client maintains connection pools and thread pools that are expensive to recreate.
// Good: Single client instance
public class MyService {
private static final AnthropicClient CLIENT = AnthropicOkHttpClient.fromEnv();
public void processRequest() {
Message response = CLIENT.messages().create(params);
}
}
// Bad: New client per request
public void processRequest() {
AnthropicClient client = AnthropicOkHttpClient.fromEnv(); // Don't do this!
Message response = client.messages().create(params);
}Close clients when shutting down your application:
import com.anthropic.client.AnthropicClient;
AnthropicClient client = AnthropicOkHttpClient.fromEnv();
try {
// Use client
Message response = client.messages().create(params);
} finally {
// Release resources
client.close();
}Use environment variables for deployment flexibility:
// Development
// ANTHROPIC_API_KEY=sk-dev-key-123
// Production
// ANTHROPIC_API_KEY=sk-prod-key-456
// ANTHROPIC_BASE_URL=https://api.production.example.com
AnthropicClient client = AnthropicOkHttpClient.fromEnv();Use withOptions() for temporary configuration changes:
// Base client with standard settings
AnthropicClient client = AnthropicOkHttpClient.fromEnv();
// High-priority request with extended timeout
AnthropicClient urgentClient = client.withOptions(opts -> {
opts.timeout(Duration.ofMinutes(5));
});
Message urgentResponse = urgentClient.messages().create(urgentParams);
// Standard requests still use base client
Message normalResponse = client.messages().create(normalParams);Install with Tessl CLI
npx tessl i tessl/maven-com-anthropic--anthropic-java@2.11.1