# Kanject.Core.Adapter

The outbound HTTP integration layer. Typed `HttpClient` registration, resilient retries, authentication and header helpers, health pings, AOT-safe JSON overloads — plus a source generator that turns declarative endpoint contracts into production-ready adapter methods.

Use it when a service needs a stable boundary around a payment gateway, shipping carrier, CRM, internal microservice, or any other HTTP API. Application code depends on a typed adapter instead of spreading URLs, credentials, serialization, and status-code handling across controllers and domain services.

## Install

```bash
dotnet add package Kanject.Core.Adapter
```

`Kanject.Core.Adapter.Annotations` (the endpoint source generator) is included transitively, so generated adapters normally need no second package reference.

## A generated adapter

Declare the contract — auth scheme, base URL, endpoints, per-endpoint headers — and the generator emits the adapter methods:

```csharp
[AdapterAuth(
    AuthScheme.ApiKey,
    SettingsType = typeof(ParcelApiOptions),
    HeaderMappings = ["X-Api-Key:ApiKey"])]
[AdapterBaseUrl(nameof(ParcelApiOptions.BaseUrl))]
[AdapterJsonSerializerContext(typeof(ParcelAdapterJsonContext))]
public partial class ParcelAdapter(
    HttpClient httpClient,
    ParcelApiOptions settings) : AbstractServiceAdapter(httpClient)
{
    private readonly ParcelApiOptions _settings = settings;

    [AdapterEndpoint(HttpVerb.Post, "v1/shipments")]
    [AdapterHeader("Idempotency-Key", "{request.IdempotencyKey}")]
    public virtual partial Task<CreateShipmentResponse?> CreateShipmentAsync(
        CreateShipmentRequest request,
        CancellationToken cancellationToken);

    [AdapterEndpoint(
        HttpVerb.Get,
        "v1/shipments/{ShipmentId}",
        NotFoundReturnsNull = true)]
    public virtual partial Task<ShipmentStatus?> GetShipmentAsync(
        ShipmentLookup request,
        CancellationToken cancellationToken);
}
```

## Two authoring styles

- **Generated endpoints** — attributes, request/response DTOs, and `partial` method signatures. Best for most integrations and documentation-first contracts.
- **Hand-written adapter** — subclass `AbstractServiceAdapter` and call `GetAsync` / `PostAsync` / `PutAsync` / `DeleteAsync` directly. Best for custom protocols, unusual response handling, or incremental migration.

Both styles share the same `AbstractServiceAdapter`, `HttpClientFactory` registration, retry policy, cancellation flow, and response helpers — you can mix them in one adapter.

## What ships with it

- **Auth schemes** — API key, bearer token, and header-mapped credentials declared once per adapter (`[AdapterAuth]`)
- **Resilient retries** — a retry policy on the shared base class, tuned for transient upstream failures
- **Settings-driven config** — base URLs, keys, and header values resolve from typed options (`{settings.…}` templates)
- **Error behaviour per endpoint** — `NotFoundReturnsNull`, custom error messages, status-code mapping
- **Health pings** — a built-in upstream reachability check (opt out per adapter with `[AdapterDisablePing]`)
- **AOT-safe JSON** — `[AdapterJsonSerializerContext]` wires source-generated serializer metadata, no reflection

---
_Source: https://www.kanject.com/docs/core-adapter/ · Kanject Docs_
