Back to blog

From vendor Swagger to a resilient typed API client

Every third-party integration starts the same way: a Swagger spec and a deadline. Here is the pattern we use to turn one into a typed, authenticated, resilient .NET client library.

Tutorials
April 8, 2026 9 min read
From vendor Swagger to a resilient typed API client

Integrating a third-party API is one of the most common tasks in enterprise software, and one of the most commonly done badly. The quick version - raw HttpClient calls, string URLs, JSON parsed inline, tokens fetched on demand - works in a demo and rots in production. We package every vendor integration as a small, self-contained client library instead, and the shape of that library is the same every time.

Start from the contract

The vendor's Swagger or OpenAPI spec is the contract, so we start there. Generating models and a base client from the spec gives you typed requests and responses for free, and it means a vendor change shows up as a compile error rather than a runtime surprise. The generated types are the foundation; everything else wraps them in production concerns.

A typed client behind an interface

The public surface of the library is a narrow interface that speaks your domain, not the vendor's. Consumers depend on IBillingProvider, not on a generated BillComApiClient with forty methods. This keeps the vendor's shape contained in one place and makes the client mockable in tests:

CSHARP
public interface IBillingProvider
{
    Task<Invoice> GetInvoiceAsync(string invoiceId, CancellationToken ct);
    Task<PaymentResult> SubmitPaymentAsync(PaymentRequest request, CancellationToken ct);
}

Register it through HttpClientFactory so the framework manages the handler lifetime and you avoid socket exhaustion:

CSHARP
builder.Services.AddHttpClient<IBillingProvider, BillingProvider>(c =>
{
    c.BaseAddress = new Uri(options.BaseUrl);
});

Authentication that refreshes itself

Most vendor APIs use OAuth2 client credentials, and the part teams get wrong is token lifecycle. Fetching a token per request is wasteful; caching one and never refreshing it fails the moment it expires. A delegating handler that acquires, caches, and refreshes the token before it lapses solves this once for every call:

CSHARP
builder.Services.AddHttpClient<IBillingProvider, BillingProvider>()
    .AddHttpMessageHandler(() => new OAuth2TokenHandler(tokenOptions));

The handler attaches the bearer token to every outgoing request, so the client code never thinks about authentication at all.

Resilience as a default, not an afterthought

A vendor you do not control will be slow or down sometimes, so resilience belongs in the client, not in every caller. Layer retry, circuit breaker, and timeout onto the same registration so transient faults are absorbed before they ever reach your domain:

CSHARP
    .AddResilienceHandler("billing", p =>
    {
        p.AddRetry(new() { MaxRetryAttempts = 3, UseJitter = true });
        p.AddCircuitBreaker(new() { FailureRatio = 0.5 });
        p.AddTimeout(TimeSpan.FromSeconds(10));
    });

Warning: Only retry idempotent calls. A retried payment submission can charge twice - guard non-idempotent operations with an idempotency key the vendor honors, or do not retry them.

Map errors to your domain

The last job of the library is to translate vendor failures into exceptions your application understands. A 404 becomes a typed InvoiceNotFound, a 429 becomes a RateLimited your caller can back off on. Leaking raw HTTP status codes into business logic couples your domain to the vendor's wire protocol; mapping them at the boundary keeps that coupling in one file.

Wrapping up

A good API client library is boring on the outside and careful on the inside: a typed domain interface, generated models from the spec, self-refreshing OAuth2, built-in resilience, and errors mapped to your domain. Package those concerns once per vendor and every consumer in your system gets a client that is safe to call without thinking. The deadline that started it all gets met, and the integration does not become next quarter's incident.

Need a tricky integration done right? Let's build it.

Keep reading

The four pillars of ConnectSoft: Factory, Platforms, Squads, and Marketplace
Company News
June 20, 2026 8 min read

The four pillars of ConnectSoft: Factory, Platforms, Squads, and Marketplace

ConnectSoft is more than a services company. Here is how four reinforcing lines - the AI Factory, live platforms, AI squads, and a marketplace - fit together into one ecosystem.

Read more
The ConnectSoft tech landscape: the stack behind our delivery
Company News
June 18, 2026 8 min read

The ConnectSoft tech landscape: the stack behind our delivery

A tour of the technologies we lean on across delivery - .NET and Blazor, Azure, messaging, data, observability, and AI - and the principles that decide what makes the cut.

Read more
Why we standardized on the Microsoft Agent Framework
Engineering
June 14, 2026 9 min read

Why we standardized on the Microsoft Agent Framework

Choosing the runtime for an autonomous agent mesh is a long-lived bet. Here is the reasoning behind picking the Microsoft Agent Framework, with MCP tools and a model abstraction at its core.

Read more

Subscribe to our newsletter

Get the latest tech insights straight to your inbox

Ready to work with us?

Let's discuss how our team can help achieve your digital goals