Result values, integrates with query() and form(), and provides deterministic cache keys for the UI layer.
Always use FetchClient or the generated SDK
If codegen is not set up yet, create aFetchClient instance directly:
How it works
Define entities and services
Your server-side entity and service definitions are the source of truth for types, routes, and
validation schemas.
SDK is generated
The codegen reads your definitions and produces TypeScript files — typed methods for every CRUD
operation and custom action on entities, plus service operations.
Generated client
The SDK produces a client factory:Result<T, FetchError> — never throws for HTTP errors.
SDK + query()
SDK methods returnQueryDescriptor objects that work directly with query():
api.tasks.list({ status: 'todo' }) share the same cache entry.
SDK + form()
SDK methods carry metadata thatform() uses for validation:
form() extracts it automatically — no need to pass a schema option unless you want to override it.
FetchClient
Under the hood, the SDK usesFetchClient — a typed HTTP client you can also use directly:
Methods
Request options
Error handling
HTTP errors are returned as typedResult values:
| Status | Error class |
|---|---|
| 400 | BadRequestError |
| 401 | UnauthorizedError |
| 403 | ForbiddenError |
| 404 | NotFoundError |
| 409 | ConflictError |
| 422 | UnprocessableEntityError |
| 429 | RateLimitError |
| 500 | InternalServerError |
| 503 | ServiceUnavailableError |
Retry configuration
'exponential', 'linear', or a custom function:
Lifecycle hooks
Streaming
For real-time data, the client supports SSE and NDJSON streaming:Pagination
List endpoints returnListResponse<T>: