One SDK. Any API. Fully typed.
The type-safe API layer for TypeScript apps. Connect to REST, GraphQL, Firebase, WebSockets, SSE — all with one consistent interface and the best type safety in the ecosystem.
Quick Start
Define requests manually
import { createClient } from "@hyper-fetch/core"; // Create a client — this is the single entry point for all your API calls const client = createClient({ url: "https://api.example.com" }); // Define a typed request — response shape is inferred everywhere from here const getUsers = client.createRequest<{ response: { id: number; name: string }[] }>()({ endpoint: "/users", method: "GET", }); // Send it — data, error, and status are fully typed const { data, error, status } = await getUsers.send();
Or generate from OpenAPI
npx @hyper-fetch/cli generate --url https://api.example.com/openapi.json
import { sdk } from "./generated"; // Every endpoint from your schema is available as a typed method const { data } = await sdk.users.list.send();
Why HyperFetch?
- 🔮 Zero guesswork — End-to-end TypeScript types from schema to response, full autocompletion, zero
any - 📡 One interface for everything — REST, GraphQL, Firebase, WebSockets, SSE — stop learning a new library for each API
- 💾 Data management built in — Caching, queuing, offline support, retries, and deduplication out of the box
- ⚡ Works everywhere — React, Next.js, Remix, Astro, Node.js, Bun — same API, every environment
Packages
Examples
Fetching data
// Send and destructure — all return values are typed const { data, error, status } = await getUsers.send();
Mutation with params and payload
// Params go in the URL, data goes in the body — both fully typed const { data, error, status } = await createUser.send({ params: { teamId: 1 }, data: { name: "Jane", email: "jane@example.com" }, });
React hooks
import { useFetch } from "@hyper-fetch/react"; const UserList = () => { // useFetch triggers the request on mount and returns typed state const { data, loading, error } = useFetch(getUsers); if (loading) return <p>Loading...</p>; if (error) return <p>Error loading users</p>; return <ul>{data?.map((u) => <li key={u.id}>{u.name}</li>)}</ul>; };
