MSW v2
WARNING
MSW plugin is currently in beta. The interface might change before it becomes stable. We encourage you to leave feedback on GitHub.
About
MSW is an API mocking library that allows you to write client-agnostic mocks and reuse them across any frameworks, tools, and environments.
The MSW plugin for Hey API generates type-safe mock handler factories from your OpenAPI spec, fully compatible with SDKs, transformers, and all core features.
Collaborators
Features
- MSW v2 support
- seamless integration with
@hey-api/openapi-tsecosystem - type-safe mock handlers
- minimal learning curve thanks to extending the underlying technology
Installation
In your configuration, add msw to your plugins and you'll be ready to generate MSW artifacts. 🎉
export default {
input: 'hey-api/backend', // sign up at app.heyapi.dev
output: 'src/client',
plugins: [
// ...other plugins
'msw',
],
};Output
The MSW plugin will generate the following artifacts, depending on the input specification.
Handler Exports
Each operation is exported as a handler creator named <operationId>Mock. These use a wildcard (*) base URL so they match requests regardless of origin. A getAllMocks function is also exported.
import { getPetByIdMock, getAllMocks } from './client/msw.gen';Usage
Static Response
The simplest way to mock an endpoint is to provide a static response object with a result property. The status property is optional — when omitted, it defaults to the operation's dominant success status code (e.g. 200).
import { setupServer } from 'msw/node';
import { getPetByIdMock } from './client/msw.gen';
const mockServer = setupServer(
// result only — status defaults to the dominant success code (200)
getPetByIdMock({ result: { id: 1, name: 'Fido' } }),
// explicit status code
getPetByIdMock({ status: 200, result: { id: 1, name: 'Fido' } }),
// type error if result type is incorrect
// @ts-expect-error
getPetByIdMock({ result: 'wrong type' }),
);Custom Resolver
For more control, pass an MSW HttpResponseResolver function. The resolver receives typed path parameters and request body when available.
import { delay, HttpResponse } from 'msw';
import { setupServer } from 'msw/node';
import { getPetByIdMock, updatePetMock } from './client/msw.gen';
const mockServer = setupServer(
// custom resolver with typed params and body
updatePetMock(async ({ request, params }) => {
const body = await request.json();
return HttpResponse.json({ id: Number(params.petId), ...body }, { status: 200 });
}),
// async resolver with delay
getPetByIdMock(async () => {
await delay(100);
return HttpResponse.json({ id: 1, name: 'Fido' });
}),
);TIP
Path parameters are typed as string because MSW normalizes all path parameters to strings. Use Number() or similar conversions if you need numeric values.
Operations Without Responses
For operations that don't define a response type, the handler creator can be invoked without arguments or with a custom resolver function.
import { deletePetMock } from './client/msw.gen';
const mockServer = setupServer(
deletePetMock(),
deletePetMock(() => new HttpResponse(null, { status: 204 })),
);Response Examples
When your OpenAPI spec includes response examples, the generated handlers will use them as default values. This means you can call the handler without arguments and it will return the example response automatically.
import { getFooMock } from './client/msw.gen';
const mockServer = setupServer(
// uses the example response from the OpenAPI spec as default
getFooMock(),
// you can still override with a custom response
getFooMock({ result: { name: 'Custom' } }),
);By default, valueSources is set to ['example'], which embeds OpenAPI examples in the generated output. To disable this, set valueSources to an empty array.
export default {
// ...other options
plugins: [
// ...other plugins
{
name: 'msw',
valueSources: [],
},
],
};All Handlers (getAllMocks)
The getAllMocks function generates handlers for all operations at once. This is useful for quickly setting up a mock server without manually listing each operation.
import { setupServer } from 'msw/node';
import { getAllMocks } from './client/msw.gen';
const server = setupServer(...getAllMocks());onMissingMock
Some operations require a response argument (because they have no default example value). The onMissingMock option controls what happens for these operations:
'skip'(default) — skips handlers that require an argument, only including operations that have default values or no response type'error'— includes all handlers, but operations without a provided response return a501error with the message'[heyapi-msw] The mock of this request is not implemented.'
// strict mode: all endpoints are mocked, missing ones return 501
const server = setupServer(...getAllMocks({ onMissingMock: 'error' }));overrides
Use overrides to provide static responses for specific operations. The keys are handler names (operation ID suffixed with Mock) and the values are the same as what you'd pass to the individual handler creator.
import { setupServer } from 'msw/node';
import { getAllMocks } from './client/msw.gen';
const server = setupServer(
...getAllMocks({
onMissingMock: 'skip',
overrides: {
getPetByIdMock: {
result: { id: 1, name: 'Fido', photoUrls: [] },
},
},
}),
);When an override is provided for a required handler, it will always be included regardless of the onMissingMock setting.
Custom Base URL
The individually exported handlers use a wildcard (*) base URL that matches requests regardless of origin. If you need handlers bound to a specific base URL, use the createMswHandlerFactory function:
import { setupServer } from 'msw/node';
import { createMswHandlerFactory } from './client/msw.gen';
const createMock = createMswHandlerFactory({
baseUrl: 'http://localhost:8000',
});
const server = setupServer(createMock.getPetByIdMock({ result: { id: 1, name: 'Fido' } }));When called without arguments, the factory infers the base URL from the OpenAPI spec's servers field.
Handler Options
Handler options can be provided. The object will be passed on to MSW helpers.
const mockServer = setupServer(getPetByIdMock({ result: { id: 1, name: 'Fido' } }, { once: true }));Known Limitations
- Query parameters are not typed in the resolver. MSW doesn't provide typed query params natively — use
new URL(request.url).searchParamsinstead. - The response type generic is omitted from
HttpResponseResolverto avoid MSW'sDefaultBodyTypeconstraint issues with union and void response types.
API
You can view the complete list of options in the UserConfig interface.
Examples
You can view live examples on StackBlitz.
Sponsors
Hey API is sponsor-funded. If you rely on Hey API in production, consider becoming a sponsor to accelerate the roadmap.
Gold

Best-in-class developer interfaces for your API.
stainless.comThe open source coding agent.
opencode.aiThe intelligent knowledge platform.
mintlify.com

