SDK-gidsen
C# en .NET
Gebruik de officiële OpenAI .NET-bibliotheek met api14: client instellen, chat, streaming, tool calling, structured output en foutafhandeling in C#.
Gebruik de officiële OpenAI .NET-bibliotheek met api14. Stel OpenAIClientOptions.Endpoint in op api14 en geef een model-id zoals openai/gpt-5-mini mee wanneer je een client aanmaakt.
Installeren
dotnet add package OpenAI
export API14_API_KEY="sk-api14-..."
Configureren
using System.ClientModel;
using OpenAI;
using OpenAI.Chat;
var credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("API14_API_KEY")!);
var options = new OpenAIClientOptions { Endpoint = new Uri("https://api14.com/api/v1") };
var client = new ChatClient(model: "openai/gpt-5-mini", credential: credential, options: options);
Elke ChatClient is aan één model gebonden; maak er één per model-id dat je gebruikt.
Lees de key uit de omgeving, user secrets of je secret store, nooit uit een appsettings.json die in versiebeheer staat. Registreer in ASP.NET Core één client als singleton; die is thread-safe.
Chat
ChatCompletion completion = await client.CompleteChatAsync("Explain vector databases in two sentences.");
Console.WriteLine(completion.Content[0].Text);
Met een systeemprompt:
ChatCompletion completion = await client.CompleteChatAsync(
[
new SystemChatMessage("You are terse."),
new UserChatMessage("What is RAG?"),
]);
Streaming
var claude = new ChatClient("anthropic/claude-sonnet-4.5", credential, options);
await foreach (StreamingChatCompletionUpdate update in claude.CompleteChatStreamingAsync("Write a haiku about APIs."))
{
foreach (ChatMessageContentPart part in update.ContentUpdate)
Console.Write(part.Text);
}
Zie Streaming.
Tool calling
using System.Text.Json;
ChatTool getWeather = ChatTool.CreateFunctionTool(
functionName: "get_weather",
functionDescription: "Current weather for a city",
functionParameters: BinaryData.FromString("""
{ "type": "object", "properties": { "city": { "type": "string" } }, "required": ["city"] }
"""));
var toolOptions = new ChatCompletionOptions { Tools = { getWeather } };
List<ChatMessage> messages = [new UserChatMessage("What's the weather in Istanbul?")];
ChatCompletion completion = await client.CompleteChatAsync(messages, toolOptions);
while (completion.FinishReason == ChatFinishReason.ToolCalls)
{
messages.Add(new AssistantChatMessage(completion));
foreach (ChatToolCall call in completion.ToolCalls)
{
using JsonDocument args = JsonDocument.Parse(call.FunctionArguments);
string city = args.RootElement.GetProperty("city").GetString()!;
messages.Add(new ToolChatMessage(call.Id, GetWeather(city))); // je eigen functie
}
completion = await client.CompleteChatAsync(messages, toolOptions);
}
Console.WriteLine(completion.Content[0].Text);
Zie Tool calling.
Gestructureerde uitvoer
var jsonOptions = new ChatCompletionOptions
{
ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat(
jsonSchemaFormatName: "person",
jsonSchema: BinaryData.FromString("""
{
"type": "object",
"properties": { "name": { "type": "string" }, "born": { "type": "integer" } },
"required": ["name", "born"],
"additionalProperties": false
}
"""),
jsonSchemaIsStrict: true),
};
ChatCompletion result = await client.CompleteChatAsync(
[new UserChatMessage("Extract: Ada Lovelace, born 1815.")], jsonOptions);
using JsonDocument person = JsonDocument.Parse(result.Content[0].Text);
Console.WriteLine(person.RootElement.GetProperty("born").GetInt32());
Zie Structured outputs.
Afbeeldingen als invoer
var vision = new ChatClient("google/gemini-2.5-flash", credential, options);
ChatCompletion described = await vision.CompleteChatAsync(
[
new UserChatMessage(
ChatMessageContentPart.CreateTextPart("What is in this picture?"),
ChatMessageContentPart.CreateImagePart(new Uri("https://example.com/photo.jpg"))),
]);
Gebruik voor een lokaal bestand ChatMessageContentPart.CreateImagePart(BinaryData.FromBytes(File.ReadAllBytes("photo.png")), "image/png"). Zie Beeld en bestanden.
Embeddings
using OpenAI.Embeddings;
var embeddings = new EmbeddingClient("openai/text-embedding-3-small", credential, options);
OpenAIEmbedding embedding = await embeddings.GenerateEmbeddingAsync("The quick brown fox");
Console.WriteLine(embedding.ToFloats().Length);
Fouten
Mislukte aanroepen gooien een ClientResultException; de ruwe response bevat de status en headers:
try
{
await client.CompleteChatAsync("Hi");
}
catch (ClientResultException ex) when (ex.Status == 402)
{
Console.Error.WriteLine("Balance too low, add funds (insufficient_balance).");
}
catch (ClientResultException ex) when (ex.Status == 429)
{
string? retryAfter = null;
ex.GetRawResponse()?.Headers.TryGetValue("Retry-After", out retryAfter);
Console.Error.WriteLine($"Rate limited, retry after {retryAfter ?? "60"}s.");
}
Zie Fouten.
Timeouts en nieuwe pogingen
De bibliotheek probeert 429 en 5xx automatisch opnieuw met exponentiële backoff. Stel het aantal pogingen en de netwerktimeout in via de options die je aan elke client meegeeft:
using System.ClientModel.Primitives;
var options = new OpenAIClientOptions
{
Endpoint = new Uri("https://api14.com/api/v1"),
NetworkTimeout = TimeSpan.FromMinutes(2),
RetryPolicy = new ClientRetryPolicy(maxRetries: 4),
};
Geef een CancellationToken mee aan elke ...Async-aanroep om de totale tijd over alle pogingen te begrenzen. Opnieuw proberen helpt niet bij daily_limit_reached of insufficient_balance. 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);