TypeScript SDKReferenceAPI

React hooks

Use @hypequery/react to generate typed hooks from your hypequery API

React hooks

Use @hypequery/react to generate type-safe hooks (useQuery, useMutation) backed by TanStack Query. Bring your exported serve({ queries }) API type into your React app without duplicating schemas.

Install and set up

npm install @hypequery/react @tanstack/react-query

Peer dependencies: react and react-dom ^18 || ^19, and @tanstack/react-query@^5.104.5. Type the hooks with InferApiType<typeof api> and a manifest from hypequery generate:manifest (TypeScript), a client generated by hypequery generate:client (Python or cloud), or hand-written types. The React guide explains which to use.

useQuery

const { data, error, isLoading } = useQuery('weeklyRevenue', {
  startDate: '2025-01-01',
});
  • name is one of your API keys
  • input matches the endpoint’s input
  • Options mirror TanStack Query (staleTime, enabled, etc.)

useMutation

const rebuild = useMutation('rebuildMetrics');
rebuild.mutate({ force: true });

Mutations share the same typed input/output data.

createHooks API

createHooks accepts a config object that controls base URL, routes, authentication and request customization. Omit the config to read the client from a HypequeryProvider instead.

interface CreateHooksConfig<TApi> {
  baseUrl: string;                           // Origin or base path for routes the manifest does not cover
  manifest?: RouteManifest;                  // Method and full path per key, from `hypequery generate:manifest` or a generated client
  config?: Record<string, { method?: string; path?: string }>; // Per-route method/path overrides, applied on top of the manifest
  token?: string | (() => string | undefined | Promise<string | undefined>); // Bearer token, or a per-request resolver
  headers?: HeaderMap | (() => HeaderMap | Promise<HeaderMap>); // Static headers or a (optionally async) resolver, called per request
  cacheKey?: string;                         // TanStack cache scope; a new scope per client when omitted
  fetchFn?: typeof fetch;                    // Custom fetch implementation
  onUnauthorized?: () => void | Promise<void>; // Called on 401; refresh credentials, then the request retries once
  api?: TApi;                                // Reads routes from `api.manifest()`; server-only modules only
}

Manifest paths are absolute, so when a manifest covers a route, baseUrl contributes only its origin (when it is a full URL). Pass api only in code that never reaches the browser: it is a value import of your server module.

Use fetchFn when you need full control. Use headers when values are static, or pass a function when you need per-request headers without rewriting fetchFn.

const { useQuery, useMutation } = createHooks<Api>({
  baseUrl: '/api/analytics',
  manifest, // from `hypequery generate:manifest`
  headers: () => {
    const tenantKey = getTenantKey();
    return tenantKey ? { 'x-tenant-key': tenantKey } : {};
  },
});

createAnalyticsHooks API

When your API registers metrics or datasets, use createAnalyticsHooks. It returns everything createHooks returns, plus four semantic hooks:

  • useMetric(name, input?, options?) — query a named metric
  • useDataset(name, input?, options?) — query a dataset (maps to the dataset:<name> route)
  • useInfiniteMetric(name, input, options?) — offset-paginated metric query
  • useInfiniteDataset(name, input, options?) — offset-paginated dataset query

CreateAnalyticsHooksConfig extends CreateHooksConfig with an optional metrics array that narrows the keys accepted by useMetric.

import { createAnalyticsHooks } from '@hypequery/react';
import type { InferApiType } from '@hypequery/serve';
import type { api } from '@/analytics/api';
// npx hypequery generate:manifest analytics/api.ts --output analytics/hypequery-manifest.json
import manifest from '@/analytics/hypequery-manifest.json';

type Api = InferApiType<typeof api>;

export const {
  useQuery,
  useMutation,
  useMetric,
  useDataset,
  useInfiniteMetric,
  useInfiniteDataset,
} = createAnalyticsHooks<Api>({
  baseUrl: '/api/analytics',
  manifest, // resolves query, metric and dataset routes
});

Semantic endpoints return { data }, plus meta when it is requested, so read rows from result.data. The infinite hooks advance pages using meta.pagination (requested via the x-include-meta header); set limit as the page size. Without a manifest or matching config entry, the semantic hooks throw rather than request a wrong URL.

HTTP methods

Routes in the manifest use the server's method. For routes the manifest does not cover, useQuery issues GET and useMutation issues POST; override a route with config: { rebuildMetrics: { method: 'POST' } }. See HTTP method configuration and auto-config from server.

Advanced options

Both hooks accept the underlying TanStack options, so you can control staleTime, retries, invalidation, manual queryClient access, etc.

Exports

ExportPurpose
createHooks<Api>(config?)useQuery, useMutation and useInfiniteQuery for an API type
createAnalyticsHooks<Api>(config?)Everything createHooks returns, plus useDataset, useMetric, useInfiniteDataset and useInfiniteMetric
createHypequeryClient<Api>(config)A request client with its own baseUrl, manifest, token, headers and cacheKey
HypequeryProviderProvides a client (and optionally a QueryClient) to hooks created without a config
useHypequeryClient()Reads the provided client, for example its cacheKey
queryOptions(options)Marks an object as TanStack options, for calls where it could be read as input
HttpErrorThe error type for non-2xx responses, with status and parsed body
ClientSchemaChangedErrorAn HttpError for a 409 CLIENT_SCHEMA_CHANGED: the endpoint changed since the client was generated

Types: QueryInput, QueryOutput, QueryOutputForInput, HttpMethod, ApiContract, HypequeryClient, HypequeryClientConfig, HeadersInput, TokenInput, QueryMethodConfig, RouteManifest, RouteManifestEntry, HypequeryProviderProps, CreateHooksConfig and CreateAnalyticsHooksConfig.

Error handling

Errors surface through TanStack Query's error state. A non-2xx response rejects with HttpError: status is the HTTP status and body the parsed response ({ error: { type, message, details? } } for hypequery endpoints; typed unknown because proxies can return anything). message is a generic description of the failed request. Network failures reject with the underlying fetch error. See Error Handling.

When to use it

  • SPA dashboards needing cached queries
  • Next.js / Remix apps already using TanStack Query
  • Agents or components calling hypequery APIs inline

If you don’t need React hooks, you can call api.execute directly on the server or use the HTTP API as-is.

On this page

Get early access to hypequery cloud.

Cloud hosts the same model you run in your backend, with a managed API and MCP server, versions, and rollback. We're letting teams in a few at a time. Join the waitlist and we'll reach out when your project can go live.

How do you want to build your analytics layer? (Optional)
What features do you most need? (Optional)

Pick as many as you like.

Only your email is required. All other questions are optional.