The application has its pages (0201); now they get data. From the API side's point of view, you are the caller: your client has to deal with status codes, ProblemDetails (K2 2.3.7) and network errors, and that should happen in one place, not in every component. This lesson builds that place, three interceptors in src/app/core/api, and shows the two ways to fetch data: httpResource for reads, HttpClient for everything else. The typed client from the OpenAPI document follows in 0203; here we still write the types by hand.

State of the checks. The code comes from a throwaway project outside the repository (Node 24.22.3, Angular 22.2.6, TypeScript 6.0.3, RxJS 7.8.2, Vitest 5.1.0). What ran: ng build (exit code 0) and ng test --no-watch with the tests of this lesson (interceptors, contact list, appointments; final state of the project after 0204: 32 tests in 7 files, exit code 0). All tests answer with HttpTestingController: no request went to a running API or into a browser. Not run: ng serve with the proxy against the Kladde API, a real network error. Where K2 names fields differently, K2 applies: check the K2 state (2.3.7 ProblemDetails, 2.12.1 continuation token). The name next for the field of the token in the response of the appointments is our assumption; the contract names only the parameter after. Statements on httpResource and interceptors come from the pages of the Angular documentation, read on the day of writing.

Making requests: HttpClient and what the types promise

HttpClient is registered with provideHttpClient(...), and inject(HttpClient) returns it. Every method returns an observable; the request goes out only when you subscribe. get<T>(url) returns the body as T. The T is a promise by the programmer: Angular checks nothing at runtime. If something else arrives, you find out only when you access it; 0203 solves that by generating the types from the contract. Until then the shapes live in one file:

src/app/core/api/vertrag.ts (excerpt):

TypeScript
export interface ContactPage {
  contacts: ContactSummary[];
  total: number;
  page: number;
  pageCount: number;
}

export interface AppointmentPage {
  appointments: AppointmentResponse[];
  next: string | null;
}

Times in this contract are strings (ISO 8601 with offset, K2 2.3.9); a string becomes a date only when you decide so.