Guide agli SDK
Java
Usa la libreria ufficiale openai-java con api14: baseUrl, chat, streaming, strumenti, output strutturato, input di immagini, errori, timeout e retry.
Usa la libreria ufficiale openai-java con api14. Imposta baseUrl nel builder del client e passa gli id dei modelli (ad esempio openai/gpt-5-mini) come semplici stringhe.
Installazione
Gradle:
implementation("com.openai:openai-java:4.+")
Maven:
<dependency>
<groupId>com.openai</groupId>
<artifactId>openai-java</artifactId>
<version>LATEST</version>
</dependency>
Poi imposta API14_API_KEY=sk-api14-... nel tuo ambiente.
Configurazione
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
OpenAIClient client = OpenAIOkHttpClient.builder()
.baseUrl("https://api14.com/api/v1")
.apiKey(System.getenv("API14_API_KEY"))
.build();
OpenAIOkHttpClient.fromEnv() legge invece OPENAI_BASE_URL e OPENAI_API_KEY, così puoi cambiare ambiente senza modificare il codice:
export OPENAI_BASE_URL="https://api14.com/api/v1"
export OPENAI_API_KEY="sk-api14-..."
Chat
import com.openai.models.chat.completions.ChatCompletion;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
.model("openai/gpt-5-mini")
.addUserMessage("Explain vector databases in two sentences.")
.build();
ChatCompletion completion = client.chat().completions().create(params);
completion.choices().get(0).message().content().ifPresent(System.out::println);
Streaming
import com.openai.core.http.StreamResponse;
import com.openai.models.chat.completions.ChatCompletionChunk;
ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
.model("anthropic/claude-sonnet-4.5")
.addUserMessage("Write a haiku about APIs.")
.build();
try (StreamResponse<ChatCompletionChunk> stream = client.chat().completions().createStreaming(params)) {
stream.stream()
.flatMap(chunk -> chunk.choices().stream())
.flatMap(choice -> choice.delta().content().stream())
.forEach(System.out::print);
}
Vedi Streaming.
Tool calling
Descrivi uno strumento come classe; l'SDK ne ricava lo JSON Schema e analizza gli argomenti riportandoli nella classe:
import com.fasterxml.jackson.annotation.JsonClassDescription;
import com.openai.models.chat.completions.*;
import java.util.Collection;
@JsonClassDescription("Current weather for a city")
static class GetWeather {
public String city;
}
ChatCompletionCreateParams.Builder builder = ChatCompletionCreateParams.builder()
.model("openai/gpt-5-mini")
.addTool(GetWeather.class)
.addUserMessage("What's the weather in Istanbul?");
while (true) {
ChatCompletionMessage message = client.chat().completions().create(builder.build())
.choices().get(0).message();
builder.addMessage(message);
if (message.toolCalls().map(Collection::isEmpty).orElse(true)) {
message.content().ifPresent(System.out::println);
break;
}
for (ChatCompletionMessageToolCall call : message.toolCalls().get()) {
GetWeather args = call.asFunction().function().arguments(GetWeather.class);
builder.addMessage(ChatCompletionToolMessageParam.builder()
.toolCallId(call.asFunction().id())
.contentAsJson(getWeather(args.city)) // la tua funzione
.build());
}
}
Il builder conserva l'intera conversazione: a ogni giro aggiunge il messaggio dell'assistente con le sue chiamate di strumento, poi un messaggio di strumento per ogni chiamata, e rinvia tutto. I campi della classe dello strumento diventano le proprietà dello schema; aggiungi @JsonPropertyDescription a un campo per dire al modello cosa significa. Nel codice di produzione limita il numero di iterazioni, così un modello che continua a chiamare strumenti non può andare in loop all'infinito. Vedi Tool calling.
Output strutturato
Passa una classe a responseFormat; l'SDK genera da essa uno JSON Schema rigoroso e analizza il contenuto di ogni choice in un'istanza. Usa un modello che elenca structured_outputs o response_format nei suoi supported_parameters:
static class Person {
public String name;
public int born;
public String city;
}
StructuredChatCompletionCreateParams<Person> params = ChatCompletionCreateParams.builder()
.model("openai/gpt-5-mini")
.responseFormat(Person.class)
.addUserMessage("Extract: Ada Lovelace, born 1815 in London.")
.build();
client.chat().completions().create(params).choices().stream()
.flatMap(choice -> choice.message().content().stream())
.forEach(person -> System.out.println(person.name + " " + person.born));
Vedi Output strutturati.
Input di immagini
import java.util.List;
ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
.model("google/gemini-2.5-flash")
.addUserMessageOfArrayOfContentParts(List.of(
ChatCompletionContentPart.ofText(ChatCompletionContentPartText.builder()
.text("What is in this picture?").build()),
ChatCompletionContentPart.ofImageUrl(ChatCompletionContentPartImage.builder()
.imageUrl(ChatCompletionContentPartImage.ImageUrl.builder()
.url("https://example.com/photo.jpg") // oppure un URL data:image/png;base64,...
.build())
.build())))
.build();
Vedi Visione e file.
Parametri aggiuntivi
I campi del gateway senza un setter tipizzato (reasoning, provider, models) passano tramite putAdditionalBodyProperty:
import com.openai.core.JsonValue;
import java.util.Map;
ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
.model("anthropic/claude-sonnet-4.5")
.addUserMessage("Prove there are infinitely many primes.")
.putAdditionalBodyProperty("reasoning", JsonValue.from(Map.of("effort", "high")))
.build();
Errori
Le risposte non 2xx lanciano sottoclassi di OpenAIServiceException, che espongono lo stato e gli header:
import com.openai.errors.OpenAIServiceException;
try {
client.chat().completions().create(params);
} catch (OpenAIServiceException e) {
if (e.statusCode() == 402) {
System.err.println("Balance too low, add funds (insufficient_balance)");
} else if (e.statusCode() == 429) {
System.err.println("Rate limited, retry after " + e.headers().values("Retry-After") + "s");
} else {
throw e;
}
}
Vedi Errori.
Timeout e retry
Per impostazione predefinita il client ripete due volte gli errori di connessione, 408, 409, 429 e 5xx con backoff esponenziale. Configura il numero di retry e il timeout nel builder, oppure per singola richiesta:
import com.openai.core.RequestOptions;
import java.time.Duration;
OpenAIClient client = OpenAIOkHttpClient.builder()
.baseUrl("https://api14.com/api/v1")
.apiKey(System.getenv("API14_API_KEY"))
.maxRetries(4)
.timeout(Duration.ofSeconds(60))
.build();
client.chat().completions().create(params,
RequestOptions.builder().timeout(Duration.ofMinutes(5)).build());
Il timeout del builder si applica a ogni tentativo. Le richieste di reasoning lunghe possono richiedere minuti, quindi dai loro un timeout più lungo per singola richiesta oppure usa lo streaming. Riprovare non serve con daily_limit_reached o insufficient_balance; intercetta RateLimitException e controlla il codice di errore prima di pianificare un altro tentativo. Vedi Limiti di frequenza.
Tutte le funzionalità
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api14.com/api/v1",
apiKey: process.env.API14_API_KEY,
});
const result = await client.chat.completions.create({
"model": "openai/gpt-5-mini",
"messages": [
{
"role": "user",
"content": "Explain vector databases in two sentences."
}
]
});
console.log(result.choices[0].message.content);