We gebruiken cookies. Cookies en browseropslag houden je ingelogd en onthouden je voorkeuren. Met je toestemming meten we ook hoe de site wordt gebruikt. Je kunt je wanneer je wilt. Zie ons cookiebeleid.

Java

SDK-gidsen

Java

Gebruik de officiële openai-java bibliotheek met api14: client instellen, chat, streaming, tool calling, structured output en foutafhandeling.

Gebruik de officiële bibliotheek openai-java met api14. Stel baseUrl in op de clientbuilder en geef model-id's (bijvoorbeeld openai/gpt-5-mini) als gewone strings mee.

Installeren

Gradle:

implementation("com.openai:openai-java:4.+")

Maven:

<dependency>
  <groupId>com.openai</groupId>
  <artifactId>openai-java</artifactId>
  <version>LATEST</version>
</dependency>

Stel daarna API14_API_KEY=sk-api14-... in je omgeving in.

Configureren

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() leest in plaats daarvan OPENAI_BASE_URL en OPENAI_API_KEY, zodat je zonder codewijzigingen van omgeving kunt wisselen:

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);
}

Zie Streaming.

Tool calling

Beschrijf een tool als klasse; de SDK leidt het JSON Schema ervan af en parset de argumenten terug naar die klasse:

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)) // je eigen functie
            .build());
    }
}

De builder bewaart het hele gesprek: elke ronde voegt het assistentbericht met zijn tool calls toe, daarna één toolbericht per aanroep, en stuurt alles opnieuw. De velden van de toolklasse worden de properties van het schema; voeg @JsonPropertyDescription aan een veld toe om het model te vertellen wat het betekent. Begrens in productiecode het aantal iteraties, zodat een model dat steeds tools aanroept niet eindeloos kan blijven lussen. Zie Tool calling.

Gestructureerde uitvoer

Geef een klasse mee aan responseFormat; de SDK genereert er een strikt JSON Schema van en parset de inhoud van elke choice naar een instantie. Gebruik een model dat structured_outputs of response_format vermeldt in zijn 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));

Zie Structured outputs.

Afbeeldingen als invoer

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") // of een data:image/png;base64,... URL
                .build())
            .build())))
    .build();

Zie Beeld en bestanden.

Extra parameters

Gateway-velden zonder getypeerde setter (reasoning, provider, models) gaan via 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();

Fouten

Responses die niet 2xx zijn, gooien subklassen van OpenAIServiceException, die de status en headers beschikbaar stellen:

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;
    }
}

Zie Fouten.

Timeouts en nieuwe pogingen

De client probeert verbindingsfouten, 408, 409, 429 en 5xx standaard twee keer opnieuw met exponentiële backoff. Configureer het aantal en de timeout op de builder, of per request:

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());

De timeout van de builder geldt voor elke poging. Lange reasoning-requests kunnen minuten duren, geef ze dus een langere timeout per request of stream ze. Opnieuw proberen helpt niet bij daily_limit_reached of insufficient_balance; vang RateLimitException af en controleer de foutcode voordat je een nieuwe poging inplant. Zie Rate limits.

Alle mogelijkheden

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);