Skip to Content
✨ New: Auth Plugin. JWT, OAuth2, API Key, and more authentication strategies out of the box. Read more... 🎉
Groups

Groups

Groups organize related endpoints under a shared namespace, with optional hooks and a basePath.

Basic Groups

import { createApiClient, group, get, post, del } from 'endpoint-fetcher'; const api = createApiClient({ users: group({ endpoints: { list: get<void, User[]>('/users'), getById: get<{ id: string }, User>((input) => `/users/${input.id}`), create: post<CreateUserInput, User>('/users'), delete: del<{ id: string }, void>((input) => `/users/${input.id}`), }, }), posts: group({ endpoints: { list: get<void, Post[]>('/posts'), getById: get<{ id: string }, Post>((input) => `/posts/${input.id}`), }, }), }, { baseUrl: 'https://api.example.com', }); await api.users.list(); await api.users.getById({ id: '123' }); await api.posts.list();

Nested Groups

Groups can contain other groups via the groups key:

const api = createApiClient({ admin: group({ groups: { users: group({ endpoints: { list: get<void, User[]>('/admin/users'), ban: post<{ id: string }, void>((input) => `/admin/users/${input.id}/ban`), }, }), reports: group({ endpoints: { daily: get<{ date: string }, Report>((input) => `/admin/reports/${input.date}`), }, }), }, }), }, { baseUrl: 'https://api.example.com' }); await api.admin.users.list(); await api.admin.users.ban({ id: '123' }); await api.admin.reports.daily({ date: '2024-01-01' });

A group can have both endpoints (direct children) and groups (nested sub-groups) at the same time.

basePath

Set basePath on a group to prefix all endpoint paths within it. The prefix accumulates across nested groups:

const api = createApiClient({ users: group({ basePath: '/users', endpoints: { list: get<void, User[]>('/'), // → GET /users/ getById: get<{ id: string }, User>((i) => `/${i.id}`), // → GET /users/123 }, groups: { posts: group({ basePath: '/posts', endpoints: { list: get<void, Post[]>('/'), // → GET /users/posts/ }, }), }, }), }, { baseUrl: 'https://api.example.com' });

Group Hooks

Hooks defined on a group apply to all endpoints in it, including nested groups:

const api = createApiClient({ protected: group({ hooks: { beforeRequest: async (url, init) => ({ url, init: { ...init, headers: { ...init.headers, Authorization: `Bearer ${getToken()}` }, }, }), }, endpoints: { me: get<void, User>('/me'), settings: get<void, Settings>('/settings'), }, }), public: group({ endpoints: { health: get<void, { status: string }>('/health'), }, }), }, { baseUrl: 'https://api.example.com' }); await api.protected.me(); // ✅ Authorization header automatically added await api.public.health(); // no auth

See Hooks for the full hook execution order across levels.