Sometimes the API you need to test doesn't exist yet. The contract is agreed, the front-end team is building against it, but the back-end is two sprints out. Mock servers in Postman fill that gap: you define example responses on a collection, Postman serves them at a real HTTPS URL, and any client (your Postman tests, a front-end app, a Newman run in CI) can hit that URL and get the predefined responses back. This lesson covers when mocks make sense, how to create one, the example-matching rules, and the limits worth knowing before you lean too hard on them. It builds directly on the masterclass Mocking and Virtualisation lesson.
What a mock server actually does
A Postman mock server takes the examples saved on your collection's requests and serves them at a generated URL like https://abc1234.mock.pstmn.io. When a request comes in, Postman matches it (by path, method, and optionally headers/body/query) against your saved examples and returns the closest one.
It's not a backend — there's no business logic, no state, no validation. It's a response replayer. Send a GET /users/1 to the mock URL → Postman finds the example you saved for GET /users/1 → returns that example's body, status, and headers. Send POST /users → Postman returns the saved 201 example regardless of the body you sent.
That makes mocks great for some things and useless for others.
Why mock servers matter for QA
Three scenarios where a mock pays for itself:
- Front-end testing before the back-end exists. The front-end team can build and test against a stable URL with realistic responses while the back-end is being written.
- Deterministic test runs in CI. Your collection in CI hits the mock URL, not the real API. No rate limits, no flaky network, no shared state. Newman runs the same suite identically every time.
- Reproducing edge cases that are hard to get from the real API. A 500 error, a 429 rate-limit response, a malformed body — easy to mock, hard to make happen on demand against a healthy production API.
Where mocks fall short: anything that depends on actual server logic. Validation rules, state transitions, side effects (writes that show up on subsequent reads), authentication checks that vary by request — none of that exists in a mock.
How a mock works, end to end
The whole flow is "save examples → flip a URL → done." No infrastructure to set up.
Saving examples — the critical step
A mock with no examples returns 501 Not Implemented for everything. The work you do is saving good examples on each request.
To save an example:
- Send the request against the real API (or hand-craft a synthetic response).
- In the response panel, click Save Response → Save as Example.
- Name the example descriptively:
200 — Single User,404 — User Not Found,400 — Validation Failed. - The example is stored on the request and is visible under the request in the sidebar (look for the example child rows).
Each request can have multiple examples — different statuses for different scenarios. The mock returns the right one based on matching rules.
A typical set of examples on a GET /users/:id request:
200 OK—/users/1→ a happy-path user object.200 OK Empty—/users/0→ an edge case where the API returns an empty response.404 Not Found—/users/9999→ the not-found case.500 Internal Server Error—/users/error→ for testing error handling.
The mock returns whichever example's path most closely matches the incoming request.
Creating the mock
- Right-click the collection in the sidebar → Mock Collection.
- Name the mock (e.g.
JSONPlaceholder Mock). - Optionally pick an environment to attach (so the mock URL is auto-saved as a variable).
- Choose privacy: Private (requires your Postman API key in the
x-api-keyheader) or Public (anyone with the URL can call it). Default to Private until you have a reason. - Click Create. Postman generates a URL like
https://abc1234.mock.pstmn.ioand saves it.
Hit it from anywhere: curl https://abc1234.mock.pstmn.io/users/1 and Postman returns the example you saved for that path.
Switching environments to use the mock
The cleanest pattern: keep your collection variable-driven ({{baseUrl}}), and have one environment per backend.
Real—baseUrl = https://jsonplaceholder.typicode.comMock—baseUrl = https://abc1234.mock.pstmn.io
Switch the environment dropdown to Mock and the same collection now hits the mock instead. No request edits. This is the headline use case for environments + mocks together.
Matching rules
Postman matches incoming requests to examples on a few axes, in priority order:
- Path and method exactness —
GET /users/1matches an example saved asGET /users/1. - Path parameter wildcards — Postman is reasonably forgiving;
GET /users/2will match an example saved asGET /users/1if no/users/2example exists. The status code returned is the one from the saved example. x-mock-response-nameorx-mock-response-idheader — to force the mock to use a specific example regardless of path. Useful for testing your client against an error response: sendx-mock-response-name: 500 — Server Errorand the mock returns that example.- Query parameter matching — examples can be saved with specific query params; an exact query match wins over a generic example.
Most of the time you won't need to think about this — match what you saved and the mock does the right thing. When testing error paths, the x-mock-response-name header is the explicit lever.
Limitations to know up front
Mocks are great for some things and bad for others. The honest limitations:
- No state. A
POSTfollowed by aGETwith the same id won't see the data you "wrote". The mock returns whatever example matches the GET, regardless of what you POSTed. - No body/header validation. The mock doesn't care if you send malformed JSON or skip required fields — it returns the saved example. If you need validation, mock isn't enough.
- No conditional logic. "Return 200 for valid users, 404 otherwise" requires you to save both examples and use header overrides to switch — there's no actual if/else.
- Free-tier limits. Postman's free plan caps mock calls per month. For heavy CI use, paid plans or self-hosted alternatives (Prism, MockServer, MSW) are worth considering.
- Mock URL is generated, not custom. You can't get
mocks.mycompany.com/...— only<id>.mock.pstmn.io.
For a full backend simulator with state and logic, Mocking and Virtualisation covers heavier-weight tools (WireMock, MockServer, Mountebank). Postman mocks are the lightweight option that fits in 30 seconds.
A practical workflow
A typical small-team workflow that uses Postman mocks well:
- Spec freeze. Back-end and front-end agree on the API shape (often as an OpenAPI spec).
- Generate the collection. Import the spec into Postman → collection with one request per operation. (Chapter 2, Lesson 3.)
- Save examples for the happy path and the most important error cases. Pull them from a sketch the back-end team produced or hand-craft from the spec.
- Create the mock, share the URL with the front-end team and CI.
- Front-end builds. They hit the mock URL during development; their tests pass against the mock.
- Back-end ships. The same Postman collection is now run against the real URL by switching environments. Most assertions still pass; the ones that don't reveal real bugs in the implementation.
The mock served as the contract. Both teams worked against the same examples. Integration is far smoother than "back-end ships, front-end discovers reality."
⚠️ Common mistakes
- Empty examples = 501 Not Implemented. A common confusion: the mock URL is generated, but no examples are saved. Every call returns 501. Save examples first, then test the mock.
- Confusing the mock for a real backend. A POST that "creates" a resource on the mock doesn't persist anything. Subsequent GETs return whatever the saved example says, not what you POSTed. Don't write tests that assume mock state across requests.
- Sharing private mocks without the API key. Private mocks require an
x-api-keyheader. If a teammate hits a private mock without the key they get 401. Either share the API key (in their environment) or set the mock to Public if the data is non-sensitive.
🎯 Practice task
Stand up a mock and run your collection against it. 25-30 minutes.
- In your
JSONPlaceholder API Testscollection, openGET User by ID(/users/1). Send. In the response panel, click Save Response → Save as Example. Name it200 — Single User. Save. - Save two more examples on the same request: one for
200 — User Two(change the URL to/users/2first, send, save the example), and one synthetic404 — User Not Foundexample with status404and body{"error": "User not found"}. To make a synthetic example: open the request → click the example dropdown next to Save → Add Example → fill in the response side manually. - Right-click the collection → Mock Collection. Name:
JSONPlaceholder Mock. Privacy: Public (for this exercise — easier setup). Create. - Postman shows the generated URL. Copy it.
- Create a new environment called
Mock. SetbaseUrlto your mock URL (e.g.https://abc1234.mock.pstmn.io). Activate it. - Re-send
GET User by ID. The request now hits the mock — confirm in the Console that the URL is the mock URL. The response should be the200 — Single Userexample you saved. - Change the URL path to
/users/9999and send. Postman should fall back to the closest example or to404 — User Not Found. Try thex-mock-response-nameheader trick: add a headerx-mock-response-name: 404 — User Not Foundto a request — the mock returns that example explicitly regardless of path. - Stretch: point a
curlcommand at the mock URL:curl https://<your-mock>.mock.pstmn.io/users/1. The same JSON comes back. Now anything — your front-end, a CI script, a hackathon teammate — can use the mock without Postman installed.
That ends Chapter 4. You can now chain requests, run data-driven suites, configure real authentication, and stand up a mock server without leaving Postman. Chapter 5 takes the same collection and runs it at scale: the Collection Runner for batch runs, Newman for the command line, HTML reports, and CI/CD integration.