Adding AI features — summaries, drafting, classification, chat — to an existing .NET application is now a common request. This guide shows how to integrate the OpenAI API in ASP.NET Core in a way that is secure, testable and affordable to run. The same architecture applies to Azure OpenAI and other LLM providers.

The architecture

  1. The web or mobile client calls your ASP.NET Core endpoint.
  2. Your API authenticates the user, checks permissions and rate limits.
  3. An AI service in your backend builds the prompt (and, for RAG, retrieves relevant data).
  4. The service calls the model provider with a server-side API key.
  5. The response is validated, logged (without sensitive data) and returned — or streamed — to the client.

Never put model API keys in a browser, mobile app or public repository. Anything shipped to a client can be extracted.

Step 1: Configuration and secrets

Store the API key in user secrets during development and in a vault (Azure Key Vault, AWS Secrets Manager) or environment variables in production. Keep the model name in configuration too, so you can change it without redeploying code.

// appsettings.json (no secrets here)
"AI": { "Model": "your-model-name" }

// the key comes from user-secrets / Key Vault / environment: AI__ApiKey

Step 2: Register a client

The official OpenAI .NET SDK provides a ChatClient. Register it once and inject it where needed.

using OpenAI.Chat;

builder.Services.AddSingleton(sp =>
{
    var config = sp.GetRequiredService<IConfiguration>();
    return new ChatClient(
        model: config["AI:Model"],
        apiKey: config["AI:ApiKey"]);
});

If you want to stay provider-neutral, Microsoft.Extensions.AI offers an IChatClient abstraction with implementations for OpenAI, Azure OpenAI and others.

Step 3: Wrap it in your own service

Don't call the SDK from endpoints directly. A small service owns prompts, limits and logging, and makes testing easy.

public sealed class SummaryService(ChatClient chat, ILogger<SummaryService> log)
{
    public async Task<string> SummarizeAsync(string text, CancellationToken ct)
    {
        if (text.Length > 20_000) throw new ArgumentException("Text too long");

        List<ChatMessage> messages =
        [
            new SystemChatMessage("Summarize the user's text in 5 bullet points. Use only the text provided."),
            new UserChatMessage(text)
        ];

        ChatCompletion result = await chat.CompleteChatAsync(messages, cancellationToken: ct);
        log.LogInformation("Summary tokens: in {In}, out {Out}",
            result.Usage.InputTokenCount, result.Usage.OutputTokenCount);
        return result.Content[0].Text;
    }
}

Step 4: Expose an endpoint

app.MapPost("/api/summaries", async (SummaryRequest req, SummaryService svc, CancellationToken ct)
        => Results.Ok(new { summary = await svc.SummarizeAsync(req.Text, ct) }))
   .RequireAuthorization()
   .RequireRateLimiting("ai");

Combine it with ASP.NET Core's rate limiting middleware so one user or tenant cannot run up your bill. For long responses, stream tokens to the client with the SDK's streaming methods and server-sent events for a responsive UI.

Step 5: Handle failures gracefully

  • Set timeouts and cancellation; model calls can be slow.
  • Retry transient errors (rate limits, network issues) with backoff — for example with Microsoft.Extensions.Http.Resilience or Polly.
  • Return a helpful fallback message when the AI feature is unavailable; the rest of your app should keep working.

Step 6: Security and data protection

  • Send only the data the task needs; mask or remove personal data where possible.
  • Review your provider's data usage and retention terms, and use enterprise terms or Azure OpenAI where your compliance needs require it — see Azure OpenAI vs OpenAI.
  • Treat model output as untrusted input: encode it before rendering and never execute it directly.
  • Guard against prompt injection, especially when the model can call tools or sees user-supplied documents. The OWASP Top 10 for LLM Applications is a useful reference.

Step 7: Measure quality and cost

Log token usage per feature and per tenant, keep a small evaluation set of real inputs with expected outputs, and re-run it whenever you change prompts or models. That is how you improve quality and control cost with evidence rather than guesswork.

Going further: RAG and agents

To answer questions from your own documents, add retrieval — see what is RAG. To let the model take actions in your system through your APIs, read AI agents for business.

Key takeaways: call the model only from your backend, keep keys in a vault, wrap calls in your own service, add rate limits, timeouts and retries, protect data, and log tokens and quality from day one.

Need AI features in your .NET product? Our AI integration services and .NET development team can help. Official documentation: OpenAI API docs.