openai-dotnet: The Official .NET Client for the OpenAI API
The official .NET library for the OpenAI API
At a glance
- What is it?
- openai-dotnet is the official C# client for the OpenAI REST API, generated from OpenAI's OpenAPI specification with Microsoft. It installs from NuGet with one command and covers chat, responses, embeddings, audio, images, batch and more, but its experimental API surface and fast release cadence set the real adoption cost.
- Who is it for?
- Adopt openai-dotnet if you are building .NET applications that call the OpenAI REST API directly and want a client generated from the OpenAPI specification rather than a hand-written wrapper. Do not adopt it if you need every API to be stable, since some client APIs are marked [Experimental] and produce a compiler error you must suppress by diagnostic ID.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What openai-dotnet solves and who it is for
Calling the OpenAI REST API from C# means handling HTTP requests, JSON serialization, streaming responses, retries and multipart uploads yourself. openai-dotnet removes that work. The README describes it as providing "convenient access to the OpenAI REST API from .NET applications", and it is generated from OpenAI's OpenAPI specification in collaboration with Microsoft, which means the client surface tracks the specification rather than being written by hand.
The audience is .NET developers who want typed client classes instead of raw HttpClient calls. The library splits the API into feature namespaces, each with a matching client class: OpenAI.Chat with ChatClient, OpenAI.Responses with ResponsesClient, OpenAI.Embeddings with EmbeddingClient, OpenAI.Audio with AudioClient, OpenAI.Images with ImageClient, OpenAI.Assistants with AssistantClient, plus Batch, Evals, FineTuning, Files, Models, Moderations, Realtime and VectorStores. If your application only needs chat completions, you pull in the package and use one class. If you are building retrieval over vector stores or running evaluations, the same package covers those paths.
One detail matters for Azure users: the README includes a section on working with Azure OpenAI, so the library is not limited to api.openai.com. It also documents a custom base URL for proxies or self-hosted OpenAI-compatible endpoints, which is the escape hatch for teams routing traffic through their own gateway.
How the client is structured: namespaces, clients and async pairs
The architecture is a thin, typed layer over the REST API. Each feature namespace exposes one client class, and the client holds the model name plus credentials. The basic chat example constructs a ChatClient with a model and an API key, then calls CompleteChat with a string and reads completion.Content[0].Text. There is no hidden state machine and no separate session object; the client is the entry point and each method maps to an endpoint.
Every synchronous method has an asynchronous variant in the same class. The README states that the asynchronous variant of ChatClient.CompleteChat is CompleteChatAsync, and that you await the async counterpart. That pairing is consistent across the library, so code written against the sync API translates to async with a rename and an await.
Credentials are handled through an ApiKeyCredential type and an OpenAIClientOptions object when you need a custom endpoint. The README's custom URL example passes both to the ChatClient constructor along with the model name. This is also how you point the client at an OpenAI-compatible service: set Endpoint to your base URL and supply the key your proxy expects.
The repository layout backs up the generated-client claim. There is a codegen/ directory, a specification/ directory, a schema/ directory, and an api/ folder holding public API listings organized by target framework. The package.json at the repository root is named openai-tsp and declares a codegen workspace, which indicates TypeScript-based code generation tooling feeds the C# output. That is a meaningful design choice: generated clients stay close to the specification but can lag or lead it depending on regeneration timing.
Installing openai-dotnet and making a first call
The package lives on NuGet under the name OpenAI. The README's install step is a single CLI command run inside your project directory:
dotnet add package OpenAIAfter that, the README notes that the code examples were written using .NET 10, while the library itself is compatible with all .NET Standard 2.0 applications. Some example syntax depends on newer language features, so if you are on an older target framework, expect to adjust the sample code rather than the library.
You need an API key before the first call. The README points to the OpenAI API key page and recommends storing the key outside source control, reading it from an environment variable or configuration file. The repository ships an .env.sample that shows the expected variable name:
OPENAI_API_KEY=<< YOUR API KEY >>The minimal chat call from the README constructs the client with the model and the environment variable, sends one message, and prints the assistant text:
ChatClient client = new(model: "gpt-5.1", apiKey: Environment.GetEnvironmentVariable("OPENAI_API_KEY"));
ChatCompletion completion = client.CompleteChat("Say 'this is a test.'");
Console.WriteLine($"[ASSISTANT]: {completion.Content[0].Text}");What you should see is a single line beginning with [ASSISTANT]: followed by the model's reply. If the key is missing or wrong, the failure surfaces at the call site, not at construction, since the constructor only stores the credential. The same .env.sample also contains CLIENTMODEL_TEST_MODE set to Playback, which is a test-mode switch used by the project's own test setup rather than something your application needs to set.
Where openai-dotnet gets in your way
The clearest limitation is stated in the README itself: some client APIs are marked with [Experimental] while their .NET design is still evolving, and using one produces a compiler error that you must explicitly suppress for its diagnostic ID. That is a deliberate choice by the maintainers, and it means a compile-time gate stands between you and those APIs. If your build treats warnings or errors strictly, you will need to add suppression attributes or project-level settings for each experimental diagnostic you touch. The README links to .NET preview API guidance and to a docs/FeatureLifecycle.md file describing how APIs are introduced and promoted to stable, so the promotion path exists, but nothing in the README promises a timeline.
A second constraint is the version cadence. Releases arrive frequently: 2.13.0 on 2026-08-10, 2.12.0 on 2026-07-01, and a 2.11.0-oidc.test1 prerelease on 2026-06-19. Frequent releases are normal for a client tracking a fast-moving API, but they raise the cost of pinning and upgrading. Teams that cannot absorb regular dependency bumps should pin an exact version and plan upgrade windows.
Finally, the library is a client, not an abstraction layer. It does not normalize differences between OpenAI and other providers beyond letting you set a custom Endpoint. If you need one interface across several model vendors, openai-dotnet gives you an OpenAI-shaped API and nothing more. The README documents the custom base URL for OpenAI-compatible endpoints, which helps, but compatibility is the other service's responsibility, not this library's.
openai-dotnet versus Semantic Kernel and hand-rolled HTTP
The obvious comparison is Semantic Kernel, Microsoft's orchestration framework. Semantic Kernel sits above a client like this one: it provides planners, plugins, memory abstractions and a model-agnostic connector layer, and it can use OpenAI as one backend among several. openai-dotnet does none of that. It exposes the REST API's own shapes, so a ChatCompletion is a ChatCompletion and a vector store is a vector store. If you want orchestration, you add a framework on top. If you want the API surface exactly as OpenAI defines it, with no intermediate concepts, this library is the shorter path.
The other alternative is calling the REST API with HttpClient and System.Text.Json. That gives you total control and zero dependency risk, and for a single endpoint it is not much code. The trade-off appears as soon as you need streaming, multipart audio uploads, batch jobs, retries, or the many response types the API returns. The README documents automatic retry behavior and observability as advanced scenarios, and those are exactly the parts you would otherwise rebuild. The generated-client approach also means new API features appear as typed methods rather than as JSON you have to parse by hand.
A middle option is the Azure OpenAI SDK, which targets the same models through Azure endpoints. The README's Azure OpenAI section suggests openai-dotnet already covers that case, so the choice is less about which SDK and more about which endpoint and authentication model you are standardizing on.
Maintenance, licensing and upgrade cost
The repository is not archived, and the last push was on 2026-09-14. Release tags are frequent and versioned, with 2.13.0 the latest stable listed. The project is licensed under MIT, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are included. That is a permissive license with few obligations, but it is still worth confirming how the notice is carried in your distribution, and this is not legal advice.
Upgrade cost is the practical maintenance question. Because the client is generated from the OpenAPI specification, a specification change can produce a client change in the next release. The repository's CHANGELOG.md is the place to check what moved between versions. The experimental-API mechanism is also a maintenance signal: when an API is promoted from experimental to stable, the suppression you added becomes dead weight, and when an experimental API changes shape, your suppressed call site may break without a deprecation cycle. Budget for reading the changelog on each bump rather than assuming patch versions are inert.
The docs/FeatureLifecycle.md file is the project's own statement of how APIs move from preview to stable, and it is the right document to read before depending on any experimental surface.
Editorial conclusion
Adopt openai-dotnet if you are building .NET applications that call the OpenAI REST API directly and want a client generated from the OpenAPI specification rather than a hand-written wrapper. Do not adopt it if you need every API to be stable, since some client APIs are marked [Experimental] and produce a compiler error you must suppress by diagnostic ID. Before committing, verify which namespaces your code touches, check whether they are experimental, and confirm your target framework against the .NET Standard 2.0 compatibility claim.
Frequently asked questions
How do I install openai-dotnet?
Install the OpenAI package from NuGet with dotnet add package OpenAI. The README notes the examples were written using .NET 10, but the library is compatible with all .NET Standard 2.0 applications.
Does openai-dotnet work with Azure OpenAI?
Yes. The README includes a section on working with Azure OpenAI, and it also documents setting a custom base URL through OpenAIClientOptions when you need an alternative endpoint.
Can I use openai-dotnet with a proxy or a self-hosted OpenAI-compatible model?
The README shows constructing a client with an ApiKeyCredential and an OpenAIClientOptions object whose Endpoint is set to your base URL. That is the documented path for proxies and OpenAI-compatible deployments.
Why does openai-dotnet give me a compiler error about an experimental API?
Some client APIs are marked with [Experimental] while their .NET design is still evolving, and using one produces a compiler error you must explicitly suppress for its diagnostic ID. The README links to .NET preview API guidance and to the project's feature lifecycle document.
Which namespaces and client classes does openai-dotnet provide?
The library is organized by feature area, with namespaces such as OpenAI.Chat, OpenAI.Responses, OpenAI.Embeddings, OpenAI.Audio, OpenAI.Images, OpenAI.Assistants, OpenAI.Batch, OpenAI.Files, OpenAI.VectorStores and others. Each namespace contains a corresponding client class, for example ChatClient in OpenAI.Chat.
Does openai-dotnet have async methods?
Yes. Every client method that performs a synchronous API call has an asynchronous variant in the same class, such as CompleteChatAsync for CompleteChat. The README shows awaiting the async counterpart instead of calling the sync method.
Community notes