Guides & concepts

Calling an endpoint

Six call shapes, one declaration.

Every endpoint carries every call shape its method and bindings permit. The ones that would be wrong are typed never.

MemberUse it forAvailable when
useQueryReading in a componentGET, path params bound
useSuspenseQueryReading under SuspenseGET, path params bound
queryOptionsPrefetch, useQueries, typed cache readsGET, path params bound
useMutationWriting from a componentpath params bound
mutationOptionsComposing a mutation elsewherepath params bound
useInfiniteQueryPaginated readsgetNextPageParam declared
fetchAnywhere without Reactpath params bound

The chain is immutable

Every withX and onX returns a new endpoint. The original is never mutated, so a shared endpoint stays reusable no matter what a call site binds or instruments.

const traced = api.users.detail
  .withHeaders({ 'X-Trace': 'on' })
  .onRequest((ctx) => log(ctx));

// api.users.detail is untouched.

Passing TanStack options through

The second argument of useQuery is TanStack’s own option type with the error channel pinned to HapiError. Everything you know still works, including select, which may reshape the result.

const { data } = api.users.list.useQuery(undefined, {
  staleTime: 30_000,
  select: (d) => d.items.length,
});
//    ^? number | undefined