In short
When fetch calls are scattered across 40 components, changing the base URL or adding an auth header becomes a weekend job. An API layer puts all of that in one place.
A dedicated, centralized module for all API calls — instead of scattering `fetch`/`axios` calls throughout components — making endpoints easy to find, test and change.

Think of it like this
The hotel reception desk
Guests don't walk into the kitchen or laundry room themselves. They call reception, and reception knows who to ask and how. Your components call the API layer, and it handles URLs, headers and errors.
Watch it happen
One call through the API layer
getCourses()
1/6The component calls a named function. It never sees a URL.
The big ideas
What you need to know
One client for every call
A single wrapper adds the base URL, auth token and JSON handling to every request.
Typed functions per endpoint
Components call getCourses() instead of writing URLs, and get typed data back.
Errors handled the same way
The client turns failed responses into errors in one shape, so the UI handles them consistently.
Easy to swap or mock
Tests and new backends only need changes in the API layer, not in components.
See it in code
Walk through the code
1// lib/api.ts2const BASE = process.env.NEXT_PUBLIC_API_URL;3 4async function request<T>(path: string, init?: RequestInit): Promise<T> {5 const res = await fetch(`${BASE}${path}`, {6 ...init,7 headers: { "Content-Type": "application/json", ...init?.headers },8 });9 if (!res.ok) throw new Error(`API ${res.status}: ${path}`);10 return res.json() as Promise<T>;11}12 13export const getCourses = () => request<Course[]>("/courses");14export const enroll = (id: string) =>15 request<void>(`/courses/${id}/enroll`, { method: "POST" });1/4The base URL is set once, in one place.
fetch doesn't throw on 404 or 500, so the res.ok check matters. Every call now fails the same way, and components never see raw URLs.
Save yourself the pain
Common mistakes
Oops
Calling fetch("https://api.example.com/...") directly inside components.
Do this instead
Wrap every endpoint in a named function in the API layer, and import that function instead.
Oops
Assuming fetch throws when the server returns 500.
Do this instead
fetch only throws on network failures. Check res.ok yourself and throw a clear error.
Your mission
Build your API layer
Quick check
Your backend moves from /api/v1 to /api/v2. With a proper API layer, what do you change?
Go deeper
- 1Extract scattered `fetch` calls in a project into a single `api/` module.
- 2Add a consistent error-handling and auth-header pattern in that one place.
- 3Notice how much easier it becomes to change a base URL or add caching afterward.
More topics at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.