Guides SDK
Java
Utilisez openai-java avec api14 : client, chat, streaming, appel d'outils, sorties structurées, vision, gestion des erreurs, délais et nouvelles tentatives.
Utilisez la bibliothèque officielle openai-java avec api14. Définissez baseUrl sur le builder du client et passez les identifiants de modèle (par exemple openai/gpt-5-mini) comme simples chaînes.
Installation
Gradle :
implementation("com.openai:openai-java:4.+")
Maven :
<dependency>
<groupId>com.openai</groupId>
<artifactId>openai-java</artifactId>
<version>LATEST</version>
</dependency>
Définissez ensuite API14_API_KEY=sk-api14-... dans votre environnement.
Configuration
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() lit à la place OPENAI_BASE_URL et OPENAI_API_KEY, ce qui permet de changer d'environnement sans modifier le code :
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);
}
Voir Streaming.
Appel d'outils
Décrivez un outil sous forme de classe ; le SDK en déduit le JSON Schema et réanalyse les arguments dans cette 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)) // votre fonction
.build());
}
}
Le builder conserve toute la conversation : chaque tour de boucle ajoute le message de l'assistant avec ses appels d'outils, puis un message d'outil par appel, et renvoie le tout. Les champs de la classe d'outil deviennent les propriétés du schéma ; ajoutez @JsonPropertyDescription à un champ pour indiquer au modèle ce qu'il signifie. Plafonnez le nombre d'itérations dans le code de production afin qu'un modèle qui n'arrête pas d'appeler des outils ne boucle pas indéfiniment. Voir Appel d'outils.
Sortie structurée
Passez une classe à responseFormat ; le SDK génère un JSON Schema strict à partir de celle-ci et analyse le contenu de chaque choix en une instance. Utilisez un modèle qui liste structured_outputs ou response_format dans ses 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));
Voir Sorties structurées.
Image en entrée
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") // ou une URL data:image/png;base64,...
.build())
.build())))
.build();
Voir Vision et fichiers.
Paramètres supplémentaires
Les champs de la passerelle sans setter typé (reasoning, provider, models) passent par 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();
Erreurs
Les réponses non 2xx lèvent des sous-classes de OpenAIServiceException, qui exposent le statut et les en-têtes :
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;
}
}
Voir Erreurs.
Délais d'attente et nouvelles tentatives
Par défaut, le client réessaie deux fois les erreurs de connexion, 408, 409, 429 et 5xx avec un backoff exponentiel. Configurez le nombre de tentatives et le délai sur le builder, ou par requête :
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());
Le délai défini sur le builder s'applique à chaque tentative. Les longues requêtes de raisonnement peuvent durer plusieurs minutes : donnez-leur un délai par requête plus long ou diffusez-les en streaming. Réessayer n'aide pas face à daily_limit_reached ou insufficient_balance ; interceptez RateLimitException et vérifiez le code d'erreur avant de planifier une nouvelle tentative. Voir Limites de débit.
Toutes les capacités
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);