npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@arxis/api

v3.0.1

Published

Type-safe Angular HTTP client wrapper for REST APIs: base URL, global headers, inject(ApiService) and provideApi(). Angular 17+.

Readme

@arxis/api — type-safe HTTP client for Angular

Stop repeating HttpClient boilerplate. Set your REST API base URL and headers once with provideApi(), then inject(ApiService) anywhere in your Angular app.

npm version npm downloads CI Angular 17+ License: MIT

Open in StackBlitz

@arxis/api is a small, typed wrapper around Angular's HttpClient for REST APIs. It gives you an ApiService with get, post, put, patch and delete, a base URL you configure once, and headers that go with every request. It uses the HttpClient of your app, so your interceptors, withFetch() and testing tools keep working.

Contents

Before and after

With HttpClient, every service repeats the base URL and the common headers:

@Injectable({ providedIn: 'root' })
export class UserService {
  private readonly http = inject(HttpClient);
  private readonly baseUrl = environment.apiUrl;
  private readonly headers = new HttpHeaders({ 'X-Api-Key': environment.apiKey });

  getUsers() {
    return this.http.get<User[]>(`${this.baseUrl}/users`, { headers: this.headers });
  }
}

With @arxis/api, you configure them once and each service only describes its endpoints:

// app.config.ts
provideApi({ url: environment.apiUrl, globalHeaders: { 'X-Api-Key': environment.apiKey } });

// user.service.ts
@Injectable({ providedIn: 'root' })
export class UserService {
  private readonly api = inject(ApiService);

  getUsers() {
    return this.api.get<User[]>('users');
  }
}

Features

  • Base URL management — Write api.get('users') instead of http.get(baseUrl + '/users').
  • Global headers — API keys and fixed headers go with every request automatically.
  • Type-safe — Generics for response types, plus typed overloads for observe: 'response' and observe: 'events'.
  • Modern Angular — providedIn: 'root', inject(), provideApi() environment providers, standalone apps and NgModules.
  • Multiple APIs — Extend ApiService for each backend, or give a lazy route its own base URL.
  • Uses your HttpClient — Interceptors, withFetch() and HttpTestingController work as usual.
  • Tiny — About 1 KB minified and gzipped.

Compatibility

| Angular version | @arxis/api | |-----------------|--------------| | 17.x and newer | ^3.0.0 | | 12.x – 16.x | ^1.7.4 |

Installation

npm install @arxis/api

Configuration

Add provideApi() to your application config:

// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideHttpClient } from '@angular/common/http';
import { provideApi } from '@arxis/api';

export const appConfig: ApplicationConfig = {
  providers: [
    provideHttpClient(),
    provideApi({ url: 'https://api.example.com' }),
  ],
};

provideHttpClient() is required in Angular 17–20. From Angular 21 HttpClient is provided by default, but you still need provideHttpClient() to add interceptors, withFetch() or other HTTP features. ApiService uses the HttpClient of your app, so all its interceptors apply to API requests.

NgModule apps

provideApi() also works in the providers of an NgModule:

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [
    provideHttpClient(),
    provideApi({ url: 'https://api.example.com' }),
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}

ApiModule.forRoot(config) is still available but deprecated.

EndPointConfig

interface EndPointConfig {
  url: string;
  globalHeaders?: Record<string, string | string[]>;
}

| Property | Type | Description | |-----------------|-----------------------------------------|--------------------------------------| | url | string | Base URL for all API requests. | | globalHeaders | Record<string, string \| string[]> | Headers injected into every request. |

If ApiService is injected and no config was provided, it throws an error that tells you to add provideApi().

Usage

Inject ApiService and use the HTTP methods:

import { Injectable, inject } from '@angular/core';
import { ApiService } from '@arxis/api';

@Injectable({ providedIn: 'root' })
export class UserService {
  private readonly api = inject(ApiService);

  getUsers() {
    return this.api.get<User[]>('users');
  }

  createUser(body: CreateUserDto) {
    return this.api.post<User>('users', body);
  }

  updateUser(id: string, body: Partial<User>) {
    return this.api.put<User>(`users/${id}`, body);
  }

  patchUser(id: string, body: Partial<User>) {
    return this.api.patch<User>(`users/${id}`, body);
  }

  deleteUser(id: string) {
    return this.api.delete<void>(`users/${id}`);
  }
}

Available methods

| Method | Signature | |----------|-----------| | get | get<T>(endpoint, params?, reqOpts?) | | post | post<T>(endpoint, body, reqOpts?) | | put | put<T>(endpoint, body, reqOpts?) | | patch | patch<T>(endpoint, body, reqOpts?) | | delete | delete<T>(endpoint, reqOpts?) |

All methods support observe: 'response' and observe: 'events' overloads.

Multiple APIs

To talk to more than one API, extend ApiService and pass the config to super():

import { Injectable } from '@angular/core';
import { ApiService } from '@arxis/api';

@Injectable({ providedIn: 'root' })
export class BillingApiService extends ApiService {
  constructor() {
    super({ url: 'https://billing.example.com' });
  }
}

The config can also come from an injection token: super(inject(BILLING_API_CONFIG)). A subclass without a constructor uses the config from provideApi().

You can also provide a different config for part of the app. provideApi() in the providers of a route creates a separate ApiService for that route and its children:

export const routes: Routes = [
  {
    path: 'admin',
    providers: [provideApi({ url: 'https://admin.example.com' })],
    loadChildren: () => import('./admin/admin.routes'),
  },
];

Features in detail

Base URL management

Configure once, use everywhere. All endpoints are relative to the base URL:

// Configured with: { url: 'https://api.example.com' }
api.get('users');       // GET https://api.example.com/users
api.post('orders', {}); // POST https://api.example.com/orders

Global headers

Inject API keys, or any fixed header, into every outgoing request:

provideApi({
  url: 'https://api.example.com',
  globalHeaders: {
    'X-Api-Key': 'key-123',
  },
})

Global headers are fixed when the app starts. For values that change, like an auth token, use an interceptor (see the FAQ).

Query parameters

Pass query params as a plain object or HttpParams:

api.get<User[]>('users', { role: 'admin', active: 'true' });
// GET https://api.example.com/users?role=admin&active=true

Response types

Control what the Observable emits:

// Body only (default)
api.get<User[]>('users');

// Full HTTP response (status, headers, body)
api.get<User[]>('users', null, { observe: 'response' });

// HTTP events (upload progress, etc.)
api.post<void>('upload', formData, { observe: 'events', reportProgress: true });

Testing

ApiService uses Angular's HttpClient, so you test your services with HttpTestingController like any other HTTP code:

import { provideHttpClient } from '@angular/common/http';
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
import { TestBed } from '@angular/core/testing';
import { provideApi } from '@arxis/api';

it('loads the users', () => {
  TestBed.configureTestingModule({
    providers: [
      provideHttpClient(),
      provideHttpClientTesting(),
      provideApi({ url: 'https://api.example.com' }),
    ],
  });
  const users = TestBed.inject(UserService);
  const httpTesting = TestBed.inject(HttpTestingController);

  users.getUsers().subscribe((list) => expect(list.length).toBe(1));

  httpTesting.expectOne('https://api.example.com/users').flush([{ id: 1 }]);
  httpTesting.verify();
});

FAQ

How do I set a base URL for HttpClient in Angular?

Add provideApi({ url: 'https://api.example.com' }) to your providers and make your requests with ApiService. Every endpoint is relative to that URL, so api.get('users') requests https://api.example.com/users. To change the URL per environment, use provideApi({ url: environment.apiUrl }).

How do I add a header to every HTTP request in Angular?

For fixed values, like an API key or Accept, use globalHeaders in provideApi(). For values that change while the app runs, use an interceptor.

How do I send an auth token with every request?

Use an HttpInterceptorFn. ApiService uses your app's HttpClient, so the interceptor applies to its requests:

export const authInterceptor: HttpInterceptorFn = (req, next) => {
  const token = inject(AuthService).token();
  return next(token ? req.clone({ setHeaders: { Authorization: `Bearer ${token}` } }) : req);
};

// app.config.ts
provideHttpClient(withInterceptors([authInterceptor])),
provideApi({ url: 'https://api.example.com' }),

How do I call more than one API with different base URLs?

Extend ApiService once per backend and pass its config to super(), or use provideApi() in the providers of a route. See Multiple APIs.

Does it work with standalone components and NgModules?

Yes. provideApi() works in ApplicationConfig, in route providers and in NgModule providers. Inject the service with inject(ApiService) or with a constructor parameter.

Which Angular versions are supported?

Angular 17 and newer, including Angular 22. For Angular 12–16, use @arxis/api@^1.7.4.

Is it compatible with withFetch(), SSR and interceptors?

Yes. @arxis/api doesn't create its own HttpClient; it uses the one you configure with provideHttpClient(), with all its features. It has no browser-only code, so it also runs with server-side rendering.

Migrating from 1.x to 3.0

  1. Angular 17 or newer is required. Apps on Angular 12–16 should stay on @arxis/api@^1.7.4.

  2. provideApi() returns EnvironmentProviders. Remove the spread:

    - ...provideApi({ url: 'https://api.example.com' }),
    + provideApi({ url: 'https://api.example.com' }),

    Like provideHttpClient(), it goes in application, route or NgModule providers, not in the providers of a component.

  3. ApiModule no longer imports HttpClientModule. Add provideHttpClient() to your providers if you don't have it yet. Before, ApiModule could replace the HttpClient setup of your app (for example, withFetch()). ApiModule is now deprecated: use provideApi().

  4. Subclasses no longer pass HttpClient to super(). ApiService gets HttpClient with inject():

     @Injectable({ providedIn: 'root' })
     export class BillingApiService extends ApiService {
    -  constructor(@Inject(BILLING_API_CONFIG) endpoint: EndPointConfig, public override http: HttpClient) {
    -    super(endpoint, http);
    +  constructor() {
    +    super(inject(BILLING_API_CONFIG));
       }
     }
  5. Import everything from @arxis/api. The package now has an exports map, so deep imports like @arxis/api/lib/endpoint-config.interface can fail to resolve.

  6. _apiServiceFactory was removed.

Contributing

Issues and pull requests are welcome. See CONTRIBUTING.md.

License

MIT © Rene Arias