Generating API Client
How to regenerate OpenAPI specs and typed API client hooks for web and mobile.
The API client generation pipeline ensures the web and mobile apps always have typed hooks that match the current API contract. The pipeline has two stages: OpenAPI spec generation and client code generation.
Pipeline Overview
Effect HttpApi Definitions
-> pnpm openapi:generate
-> apps/api/openapi.json
-> pnpm api:client:generate
-> apps/web/lib/api/generated/
-> apps/mobile/lib/api/generated/Step 1: Generate OpenAPI Spec
When you add or modify API routes, regenerate the OpenAPI spec:
pnpm openapi:generateThis reads the Effect HttpApi definitions in apps/api/src/ and produces apps/api/openapi.json. The spec includes all route endpoints with request/response schemas, x-ddd metadata with domain invariant markers, and per-route x-invariants annotations.
Step 2: Generate Client Hooks
Regenerate the typed client code from the OpenAPI spec:
# Regenerate web + mobile clients
pnpm api:client:generate
# Or regenerate mobile client only
pnpm mobile:generate:apiWeb Client
The web client is generated by Orval using the configuration at apps/web/orval.config.ts. Generated files land in apps/web/lib/api/generated/.
The generated hooks use a custom Axios mutator defined in apps/web/lib/api/orval-mutator.ts that injects the auth token from lib/auth-token.ts and points requests to API_BASE_URL from lib/env.ts.
Mobile Client
The mobile client follows the same Orval-based generation pattern, producing typed API hooks adapted for React Native.
When to Regenerate
Regenerate after any of these changes:
| Change | Regenerate |
|---|---|
| Added a new API route | openapi:generate then api:client:generate |
| Modified route request/response schemas | openapi:generate then api:client:generate |
| Changed URL parameters or query params | openapi:generate then api:client:generate |
| Changed authentication behavior | openapi:generate then api:client:generate |
Updated contracts in packages/contracts | openapi:generate then api:client:generate |
Required Artifacts
The invariant checker validates that these files exist:
| Artifact | Purpose |
|---|---|
apps/api/openapi.json | Generated OpenAPI spec |
apps/web/orval.config.ts | Orval configuration |
apps/web/lib/api/orval-mutator.ts | Custom Axios mutator |
apps/web/lib/api/generated/ | Generated client directory (must not be empty) |
It also validates that the root package.json includes an api:client:generate script and apps/web/package.json includes a generate:api script.
Validation
After regenerating, run the full check suite:
pnpm lint && pnpm type-check && pnpm testThis catches any mismatches between the API spec and the consuming client code.