Skip to main content

Angular 17+ · MIT licensed · zero UI dependencies

ngx-api-client

HttpClient gives you a request. It doesn't give you a policy. This library is the versioning, error normalisation, retry and loading logic every Angular app rewrites — extracted and made configurable.

npm install @ismailza/ngx-api-client

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) requests
https://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.

Read the installation guide