← Files PostmanARCHIVED FILE

skills/api-mocking/SKILL.md

8.75 KB · Oct 2, 2026 · 00:22 UTC

↓ Download file

---
name: api-mocking
description: Stands up a fake backend that behaves like a real API — from a collection or an OpenAPI spec, running locally or pushed to Postman's cloud for a durable URL — plus request-time scenario and status-code overrides for testing failure paths. Use when the user asks to "mock this API," "create a mock server," "fake the backend," "run tests without hitting the real API," or "simulate an error/out-of-stock response." Covers `postman mock`. Depends on bootstrap for the workspace id only once a mock is pushed to the cloud (`-w`, or the workspace linked in `.postman/resources.yaml`) — generating and running a mock locally needs nothing from bootstrap.
---

# API Mocking

## Overview

This skill covers the Postman CLI (`postman mock`) for **Code Mocks** — the
code-based mock product. It is not the postman-app UI (Local Mode sidebar,
Agent Mode tools, Simulations), nor the older classic/collection mocks that
serve saved collection examples from a `*.mock.pstmn.io` URL — that's a
different product (the MCP `createMock` flow), not this skill.

A **local** mock is two files on disk: `config.yaml` (name, port, scenarios) and
`default.js` — a plain Node HTTP server, and the mock itself, not a wrapper
around one. Generating, inspecting, running, and calling a local mock work for
a logged-out guest. Only sharing it — pushing to the cloud and deploying a
durable URL — needs `postman login`. The progression is one model in three
places: local folder ──`push`──▶ Code Mock (cloud definition) ──`deploy`──▶
Mock Server (the reachable URL).

Default path: write a local folder, then `mock push` later if something other
than you needs to hit it over the network (a teammate, CI elsewhere, a webhook
sender). A purely local mock answering a `postman request` on your machine
never needs cloud. The exception is `generate -w`, which creates the mock in a
workspace only and writes no local files — use that only when you intentionally
skip the repo copy.

## Process

1. **Generate.** `postman mock generate -n NAME` with no source scaffolds a
   sample shopping-cart mock (`POST /cart/items`, `GET /cart`, `POST /checkout`)
   — the fastest way to a server that already answers, useful whenever the
   point is exercising mock *behavior* rather than a specific API's shape. Pass
   a real source — `postman mock generate SOURCE -n NAME`, where `SOURCE` is a
   collection file/directory or an `openapi.yaml` — when the endpoints need to
   mirror an actual API. Either form writes `config.yaml` + `default.js` into
   `postman/mocks/NAME/` (default port 4500).
   - `postman mock generate SOURCE --update ./postman/mocks/NAME` regenerates
     the default handler from the source in place, keeping the existing name,
     port, and scenarios. `--update` still needs the `SOURCE`; it cannot be
     combined with `--output`.
   - `-w <workspaceId>` saves the mock to a cloud workspace *instead of* the
     repository — it writes no local files and requires being logged in. Cannot
     be combined with `--output`, `--force`, or `--update`. Prefer local
     generate + later `push` when you still need `mock run` from a folder.
2. **Run it.** `postman mock run ./postman/mocks/NAME` starts the server and
   prints the bound URL (`... at http://localhost:PORT`). If the port in
   `config.yaml` is taken and `--port` wasn't passed explicitly, it falls back
   to a free OS-assigned port instead of erroring — read the real port off that
   line rather than assuming the configured one. Naming `--port N` explicitly
   makes a taken port a hard error; `--port auto` always picks a free one.
3. **Call it.** Plain `postman request localhost:PORT/route` returns the
   default scenario's response. Two headers can change that per-request, with no
   restart: `x-mock-scenario: <name>` selects a scenario the mock defines
   (valid names live in `config.yaml`); a name the mock doesn't define is not an
   error — it falls back to the default scenario. `x-mock-response-code: <code>`
   filters an endpoint's saved example responses to the one with that status, so
   it only changes anything when that endpoint actually has an example for that
   code — mocks generated from a collection/spec with multiple example statuses
   honor it; the built-in sample mock has one response per route and ignores it.
   A wrong route comes back as `Endpoint not defined`. There's no hot reload: a
   `default.js` edit does nothing until you Ctrl+C the running server and
   `mock run` it again.
4. **Push it, if it needs to leave your machine.**
   `postman mock push ./postman/mocks/NAME` is safe to re-run — `Created` the
   first time, `Updated` after — and records the cloud mapping in
   `.postman/resources.yaml`; commit that change. If a mock server is already
   live for this mock, the push updates what it serves.
5. **Deploy it, for a URL that outlives your terminal.**
   `postman mock deploy CLOUD_ID -s SLUG -y` prints
   `https://SLUG.mock.<team-domain>.postman.dev`. Deployed private by default —
   callers need a Postman API key (`x-api-key`) — add `--public` only when the
   mock should be reachable by anyone with the URL. `--auto-deploy` re-publishes
   the live server automatically whenever the mock changes; even without it, a
   later `push` already updates a live server, so you only re-`deploy` for the
   first URL or after taking the server down.
6. **See who's calling it.** `postman mock get CLOUD_ID` (table or `--json`)
   returns `mockServerId`; feed that into `postman mock log MOCK_SERVER_ID` for
   call entries (filter with `--method` / `--status` / `--path` / `--since` /
   `--until` / `--limit`, or `--json`). An empty log means the URL genuinely
   hasn't been hit — a rejected caller still shows up, recorded with its failing
   status code.
7. **Tear down.**
   - Local: `postman mock delete ./path --yes` — refuses while that mock is
     **running** locally; stop `mock run` first.
   - Cloud: `postman mock delete CLOUD_ID --yes` — refuses while the mock is
     **running locally** *or* **deployed**; stop the local run and take the
     mock server down first.
   Cloud delete doesn't touch `.postman/resources.yaml`; drop that line by hand
   afterward or the repo keeps claiming a mock that's gone.

To point real request/assertion runs at a mock instead of hand-editing
base-URL variables, see the `api-testing` skill's `--use-mock`/`--mock` flags
on `collection run`.

## The two ids that matter

- **Code-mock id** — the `id` in `config.yaml`, and the id that `push` and
  `generate -w` print (often the same value). Use it for `get`, `deploy`,
  `delete`, and `run` by cloud id.
- **`mockServerId`** — a different value from `mock get CLOUD_ID` (table or
  `--json`). Use it for `mock log`, and nothing else.

## Critical Rules

1. **When you're not signed in, every gated cloud command fails closed:**
   `Authentication required. Run postman login or provide --api-key`, exit 1,
   nothing half-done. (Signed in but lacking access fails differently — a
   permission or missing-workspace error.) Whether a command is gated is decided
   by what you pass it, not the verb — `mock get`/`mock run` take either a local
   path (ungated) or a cloud ID (gated); `mock list` is gated only when called
   with no path.
2. **`push` is what moves an existing local mock to the cloud — `-w` at
   `generate` time is optional, not a fork you must choose up front.** A mock
   built as a guest can be pushed and deployed later with no rework. Do not
   assume `generate -w` left a `postman/mocks/NAME/` folder to `run`.
3. **`--public` on `deploy` is the one action here with real exposure** — it
   stands up a server anyone with the URL can hit, with no API key. The default
   (private) is the safe one; confirm intent before adding it.
4. **To change a mock:** refresh it from a source with
   `postman mock generate SOURCE --update PATH`, or edit `default.js` by hand
   and restart `mock run`. Never pass a code-mock id to `mock log` — that
   command takes a `mockServerId`.
5. **`-w`/`--workspace` only exists on `generate`, `list`, `push`, and
   `deploy`.** `get`, `run`, `log`, and `delete` already take a path or an id
   that says where the mock is — there's nothing left for `-w` to resolve on
   those.

## Verification

A mock isn't done because `generate` or `run` exited 0 — hit it with
`postman request` and check the actual status/body, or `mock get CLOUD_ID
--json` for a cloud one, then state whether it ended up local or cloud, and
(if deployed) private or public. For a scenario check, confirm a *valid* name
from `config.yaml` actually changed the response — a typo'd name falls back to
the default, so a 200 alone proves nothing. For a status-code check, use an
endpoint that has an example for that code (not the sample mock). A passing
exit code from `request` is not enough.

SHA-256: 6ce9c0cd72953bc947f183ec682793c47a0a8bf59331261f595870bbc53946fe