A policy layer, not another wrapper
Everything an ad-hoc ApiService accumulates over a project's lifetime — extracted, typed and made configurable.
URLs from configuration
Base URL, an optional path prefix and an optional version segment, assembled once and overridable per request. Your services just name the endpoint.
Versioning, four ways
URL segment, query parameter, custom header or media type — with your own naming, or turned off entirely. Pin a single call to an older version when you need to.
One error shape
RFC 9457 problem+json, a plain-text proxy page and a dropped connection all arrive as the same typed ApiError. Branch on code, never on prose.
Retry that behaves
Exponential backoff with jitter, Retry-After honoured, non-idempotent methods skipped by default. Configurable globally and per call.
Per-request options
Retry, loading, error handling and messages are decided per request and carried to the interceptors through HttpContext — not through shared mutable state.
No UI dependency
The library renders nothing. Plug in your own error and success handlers; the peer dependencies stay @angular/core, @angular/common and rxjs.
Configure once, then just name the endpoint
Where the URL comes from, what happens on a 503, and how a failure reaches the user are decisions you make in one place — not in every service.
1. Set the policy in app.config.ts
provideApi({
baseUrl: 'https://api.example.com',
prefix: 'api',
version: 1,
versioning: 'url',
retry: { maxRetries: 3, initialDelay: 1000 },
});
2. Write services that say nothing about it
@Injectable({ providedIn: 'root' })
export class OrderService {
private readonly api = inject(ApiService);
list(page: number, size: number) {
return this.api.getPage<Order>('/orders', page, size);
}
}
list(0, 20) requestshttps://api.example.com/api/v1/orders?page=0&size=20
retries on a 503, normalises any failure into one ApiError, and toggles a loading signal on the way.
Ready to drop it in?
Install the package, add provideApi() and pick your interceptors. Nothing else in your application has to change.