Java
Obstruo exposes an OpenAI-compatible API. Any Java library that supports a custom base URL works with Obstruo. This page covers the official OpenAI Java SDK and Spring AI.
Prerequisites
- An ObstruoKey and endpoint URL - see Quick Start
- A Logical Model configured in your project
- Java 17 or later
OpenAI Java SDK
Add the dependency (Maven):
<dependency>
<groupId>com.openai</groupId>
<artifactId>openai-java</artifactId>
<version>0.8.0</version>
</dependency>
Or Gradle:
Chat completions
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.ChatCompletion;
import com.openai.models.ChatCompletionCreateParams;
import com.openai.models.ChatCompletionUserMessageParam;
OpenAIClient client = OpenAIOkHttpClient.builder()
.apiKey(System.getenv("OBSTRUO_API_KEY"))
.baseUrl(System.getenv("OBSTRUO_BASE_URL"))
.build();
ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
.model("obstruo-chat")
.addMessage(ChatCompletionUserMessageParam.builder()
.content("Summarise this contract: ...")
.build())
.build();
ChatCompletion completion = client.chat().completions().create(params);
System.out.println(completion.choices().get(0).message().content().orElse(""));
Streaming
client.chat().completions().createStreaming(params).stream()
.flatMap(chunk -> chunk.choices().stream())
.map(choice -> choice.delta().content().orElse(""))
.forEach(System.out::print);
Embeddings
import com.openai.models.CreateEmbeddingResponse;
import com.openai.models.EmbeddingCreateParams;
EmbeddingCreateParams embeddingParams = EmbeddingCreateParams.builder()
.model("obstruo-embedding")
.input(EmbeddingCreateParams.Input.ofString("The quick brown fox"))
.build();
CreateEmbeddingResponse result = client.embeddings().create(embeddingParams);
List<Double> vector = result.data().get(0).embedding();
Spring AI
If you are using Spring Boot, Spring AI provides a ChatClient that accepts a custom base URL:
# application.yml
spring:
ai:
openai:
api-key: ${OBSTRUO_API_KEY}
base-url: ${OBSTRUO_BASE_URL}
chat:
options:
model: obstruo-chat
@Service
public class AiService {
private final ChatClient chatClient;
public AiService(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
public String ask(String question) {
return chatClient.prompt()
.user(question)
.call()
.content();
}
}
Environment variables
export OBSTRUO_API_KEY="your-obstruo-key"
export OBSTRUO_BASE_URL="https://api.obstruo.ai/your-org/v1"
OpenAIClient client = OpenAIOkHttpClient.builder()
.apiKey(System.getenv("OBSTRUO_API_KEY"))
.baseUrl(System.getenv("OBSTRUO_BASE_URL"))
.build();
Reading gateway metadata
The openai-java SDK does not expose extra response fields. Use java.net.http.HttpClient to read the obstruo key directly:
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
var http = HttpClient.newHttpClient();
var body = """
{"model":"obstruo-chat","messages":[{"role":"user","content":"Hello!"}]}
""";
var req = HttpRequest.newBuilder()
.uri(URI.create(System.getenv("OBSTRUO_BASE_URL") + "/chat/completions"))
.header("Authorization", "Bearer " + System.getenv("OBSTRUO_API_KEY"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
var resp = http.send(req, HttpResponse.BodyHandlers.ofString());
// Parse resp.body() with your JSON library of choice (Jackson, Gson, etc.)
// The obstruo field has this structure:
// {
// "routing": { "resolved_model": "gpt-4o-mini", "provider_type": "OpenAI", "duration_ms": 412 },
// "redaction": { "total_entities": 0, "by_category": {}, "duration_ms": 3 }
// }
// Streaming header, available on the HttpResponse directly:
var streamHeader = resp.headers().firstValue("x-obstruo-pii-state");
// "no-pii" | "redacted" | "disabled"
Next steps
- Configure PII redaction: Redaction
- Configure safety rules: Guardrails