createFetchClient
The createFetchClient function creates a type-safe client for your API to be used in browser (or any fetch-capable) environments. It uses a Proxy to dynamically build request URLs based on the property access path, matching the structure defined in defineApi.
import { createFetchClient } from "@toapi/client";import type { api } from "./api"; // Your API definition type
const client = createFetchClient<typeof api.routes>("https://api.example.com");
// Usageawait client.users.get();await client.users["123"].post({ name: "New Name" });Signature
Section titled “Signature”function createFetchClient<Routes>( apiUrl: string, options?: Options,): Client<Routes>;The Routes type parameter is the type of your server’s routes map (typeof api.routes). ApiDefinition wraps that map, so pass api.routes — not api itself. It drives inference for every path, query, body, and response type on the returned Client.
Parameters
Section titled “Parameters”apiUrl
Section titled “apiUrl”Type: string
The base URL of your API server (e.g., https://example.com/api). Every request path is appended to this value.
options
Section titled “options”Type: object (optional)
| Property | Type | Default | Description |
|---|---|---|---|
fetch |
(url: string, init: RequestInit) => Promise<Response> |
global fetch |
Custom fetch implementation. Useful for mocking, server-side rendering, or adding global middleware/interceptors. |
minTTL |
number |
5000 |
Milliseconds a cache entry with no active subscribers is retained before being dropped. |
maxOverdueTTL |
number |
1000 |
Upper bound (ms) of the random jitter added when scheduling background revalidations, to avoid stampedes. |
logger |
Logger |
console |
Object with an optional error(err) method used to report fetch/revalidation errors. |
invalidationsUrl |
string | false |
apiUrl + "/__tapi/invalidations" |
URL of the server-sent invalidation stream. Pass false to disable server-push revalidation entirely, or a string to point at a custom endpoint. |
Return value
Section titled “Return value”Returns a Client<Routes> — a proxy whose properties mirror your API structure. See How routes map to methods for the full mapping.
Client methods
Section titled “Client methods”For any route path, you can call standard HTTP methods.
.get(query?, req?)
Section titled “.get(query?, req?)”Performs a GET request.
query(optional) — an object of query parameters. Required only if the route schema declares required query params; otherwise optional.req(optional) — a standardRequestInit.- Returns — a
Promiseresolving to the typed response data, augmented with a.subscribe()method for cache updates.
const users = await client.users.get({ active: true });.post(body?, req?) · .put(body?, req?) · .patch(body?, req?)
Section titled “.post(body?, req?) · .put(body?, req?) · .patch(body?, req?)”Performs a mutation request.
body— the request body (a JSON-serializable value or aFormDatainstance).req(optional) — aRequestInitthat may also carryqueryparams viareq.query.- Returns — a
Promiseresolving to the response data, augmented with a.revalidatedpromise that settles once tag-based revalidation triggered by the response has completed.
await client.users.post({ name: "Alice" });
// with query paramsawait client.users.post({ name: "Alice" }, { query: { notify: true } });.delete(query?, req?)
Section titled “.delete(query?, req?)”Performs a DELETE request (no body).
query(optional) — query parameters.req(optional) — request configuration.- Returns — a
Promiseaugmented with.revalidated, like the other mutations.
.revalidate(query?)
Section titled “.revalidate(query?)”Forces a re-fetch of the cached GET entry for the same URL and resolves once it completes. Use it to imperatively refresh data. See Revalidation & subscriptions.
Features
Section titled “Features”Smart caching & deduplication
Section titled “Smart caching & deduplication”The client caches in-flight and resolved GET requests by URL. If you call client.users.get() multiple times while a request is pending, only one network call is made and all callers share the result.
Tag-based revalidation
Section titled “Tag-based revalidation”The client tracks cache tags sent by the server via the X-TAPI-Tags header on GET responses (specified server-side with cache: { tags: [...] }). When a mutation response includes tags matching cached GET requests, those requests are invalidated and re-fetched if they have active subscribers. The client can also receive tags pushed from the server over the invalidationsUrl stream.
Subscriptions
Section titled “Subscriptions”The promise returned by .get() is augmented with a .subscribe() method, useful for integrating with React hooks or other state management to listen for cache updates.
const promise = client.users.get();const unsubscribe = promise.subscribe((next) => { next.then((data) => console.log("Data updated:", data));});Logger
Section titled “Logger”Logger is re-exported from @toapi/common. It is a minimal interface used for error reporting:
interface Logger { error?: (error: unknown) => void | Promise<void>;}Pass one via options.logger to route client-side fetch and revalidation errors to your own logging system.