@postman/postman-plugin 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -32
- package/dist/hosts/opencode-config.js +147 -0
- package/dist/hosts/opencode.js +315 -34
- package/dist/hosts/shared.js +10 -3
- package/dist/source.js +19 -5
- package/dist/system.js +20 -1
- package/hooks/session-start-context.md +1 -1
- package/mcp.pi.json +2 -2
- package/package.json +1 -1
- package/skills/api-discovery/SKILL.md +23 -7
- package/skills/api-documentation/SKILL.md +21 -3
- package/skills/api-engineer/SKILL.md +11 -11
- package/skills/api-mocking/SKILL.md +46 -18
- package/skills/api-monitoring/SKILL.md +3 -2
- package/skills/api-simulation/SKILL.md +186 -0
- package/skills/api-simulation/reference/sim_yaml_schema.md +112 -0
- package/skills/api-testing/SKILL.md +4 -3
- package/skills/bootstrap/SKILL.md +46 -32
- package/skills/bootstrap/reference/cli_installation.md +4 -3
- package/skills/ci-integration/SKILL.md +10 -9
- package/skills/datasets/SKILL.md +6 -5
- package/skills/flows/reference/flow_cli_flags.md +1 -1
- package/skills/variables/SKILL.md +106 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# `.sim.yaml` schema
|
|
2
|
+
|
|
3
|
+
The file `postman simulation run <filepath>` reads. It lives in
|
|
4
|
+
`postman/simulations/NAME.sim.yaml`, beside the `postman/mocks/` folders it
|
|
5
|
+
composes. `postman simulation create` writes one; the Postman app writes the
|
|
6
|
+
same shape with `id:` fields added.
|
|
7
|
+
|
|
8
|
+
```yaml
|
|
9
|
+
id: 01a110fc-e3f5-77eb-af59-0a711a509960 # written by the Postman app
|
|
10
|
+
simulation: checkout-dev
|
|
11
|
+
routing: path
|
|
12
|
+
mocks:
|
|
13
|
+
- id: 01a110fc-e344-72ca-9d0c-1bb83b99ec2a # written by the Postman app
|
|
14
|
+
routeKey: products
|
|
15
|
+
path: ../mocks/products/config.yaml
|
|
16
|
+
scenarios:
|
|
17
|
+
- path: ../mocks/products/default.js
|
|
18
|
+
- routeKey: shopping-cart
|
|
19
|
+
path: ../mocks/shopping-cart/config.yaml
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Root
|
|
23
|
+
|
|
24
|
+
| Key | Required | Notes |
|
|
25
|
+
| --- | --- | --- |
|
|
26
|
+
| `simulation` | Yes | The simulation's name. |
|
|
27
|
+
| `mocks` | Yes | Non-empty list of members. |
|
|
28
|
+
| `routing` | No | `path` (default) or `header`. Any other value means `path`. |
|
|
29
|
+
| `id` | No | The simulation's id in its workspace. A local run ignores it; leave it as written. |
|
|
30
|
+
|
|
31
|
+
## Member
|
|
32
|
+
|
|
33
|
+
| Key | Required | Notes |
|
|
34
|
+
| --- | --- | --- |
|
|
35
|
+
| `path` | Yes | The mock's `config.yaml`, or a `.js` handler. Relative paths resolve from the `.sim.yaml`'s folder, then from the working directory. `file` is a legacy alias. |
|
|
36
|
+
| `routeKey` | No | The member's address. Lowercase letters, digits, `-` and `_`, at most 64 characters, unique per simulation. Defaults to the kebab-cased name. |
|
|
37
|
+
| `name` | No | Display name. Defaults to the mock's folder name for a `config.yaml`, else the file name. Must be unique. |
|
|
38
|
+
| `scenarios` | No | Fault conditions, below. |
|
|
39
|
+
| `id` | No | The mock's id in its workspace. A local run ignores it. |
|
|
40
|
+
| `port` | No | Ignored by `simulation run`, which gives each member an internal port. |
|
|
41
|
+
|
|
42
|
+
## Routing
|
|
43
|
+
|
|
44
|
+
- **`path`**: a member is at `http://localhost:<port>/<routeKey>`. The first
|
|
45
|
+
path segment selects the member and is stripped, so `/payments/cart` reaches
|
|
46
|
+
the `payments` member as `/cart`. Point the service's base URL for that
|
|
47
|
+
dependency at `http://localhost:<port>/<routeKey>`.
|
|
48
|
+
- **`header`**: every member shares `http://localhost:<port>`, and the caller
|
|
49
|
+
picks one with an `x-mock-slug: <routeKey>` header. Use it only when the
|
|
50
|
+
caller can send that header.
|
|
51
|
+
|
|
52
|
+
The router answers on its own, without reaching a member:
|
|
53
|
+
|
|
54
|
+
| Response | Cause |
|
|
55
|
+
| --- | --- |
|
|
56
|
+
| `400 {"error":"Prefix the request path with the member routing token, e.g. /<routeKey>/path."}` | No routeKey under `path` routing: the path was `/`. Under `header` routing the error asks for the `x-mock-slug` header instead. |
|
|
57
|
+
| `404 {"error":"Unknown simulation member '<x>'.","available":[...]}` | `<x>` isn't a routeKey. Under `path` routing this is often a client that dropped the base URL's path, so `<x>` is the endpoint's own first segment. |
|
|
58
|
+
|
|
59
|
+
## `scenarios`
|
|
60
|
+
|
|
61
|
+
Each entry is a selection, and only its `overrides.conditions` inject faults:
|
|
62
|
+
|
|
63
|
+
```yaml
|
|
64
|
+
scenarios:
|
|
65
|
+
- overrides:
|
|
66
|
+
conditions:
|
|
67
|
+
latency:
|
|
68
|
+
delay_ms: 250 # hold each request 250 ms, then go on
|
|
69
|
+
error:
|
|
70
|
+
status_code: 503 # every request fails with 503
|
|
71
|
+
rate_limit:
|
|
72
|
+
requests_per_minute: 30 # the 31st request in a minute gets 429
|
|
73
|
+
chaos:
|
|
74
|
+
failure_rate: 10 # 10% of requests fail with 500
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
This example sets all four to show their fields. They run in a fixed order,
|
|
78
|
+
`latency`, `error`, `rate_limit`, `chaos`, whatever order you write them in,
|
|
79
|
+
and the first to fail a request ends it: with `error` set, `rate_limit` and
|
|
80
|
+
`chaos` never fire. Set one failure at a time, optionally with `latency`.
|
|
81
|
+
|
|
82
|
+
The mock's default handler always serves, and conditions run in front of it.
|
|
83
|
+
An entry with only `path` or `id`, as the Postman app writes, injects nothing.
|
|
84
|
+
Unknown condition names are ignored, so a misspelled one fails silently.
|
|
85
|
+
`overrides.bypass` prints a warning and is ignored.
|
|
86
|
+
|
|
87
|
+
The legacy form `- type: error` with `config: { status_code: 503 }` is still
|
|
88
|
+
accepted and validated strictly: an unknown `type` is an error.
|
|
89
|
+
|
|
90
|
+
| Condition | Field | Effect |
|
|
91
|
+
| --- | --- | --- |
|
|
92
|
+
| `latency` | `delay_ms` (positive number) | Holds each request that long, then serves it normally. |
|
|
93
|
+
| `error` | `status_code` (integer 400–599) | Every request returns that status with `{"error":{...},"scenario":"error"}`. |
|
|
94
|
+
| `rate_limit` | `requests_per_minute` (positive integer) | Requests over the limit return `429` with a `Retry-After` header and `"scenario":"rate_limit"`. |
|
|
95
|
+
| `chaos` | `failure_rate` (0–100) | That percentage of requests, chosen at random, return `500` with `"scenario":"chaos"`. |
|
|
96
|
+
|
|
97
|
+
A condition applies to every route on its member. To fail one endpoint while
|
|
98
|
+
its siblings succeed, split that endpoint into its own mock.
|
|
99
|
+
|
|
100
|
+
## `simulation run`
|
|
101
|
+
|
|
102
|
+
| Flag | Notes |
|
|
103
|
+
| --- | --- |
|
|
104
|
+
| `-p, --port <n\|auto>` | Port to serve on. Defaults to 3000, and silently falls back to a free port if 3000 is busy. An explicit port fails instead. |
|
|
105
|
+
| `--output ndjson` | One JSON event per line on stdout, instead of the default readable log; messages go to stderr: `listening` (port, url, each member's `routeKey` and `address`); `request`, one per request a member served (`routeKey`, `method`, `path`, `statusCode`, `duration` in ms, headers and bodies); and `summary` on shutdown (`requestsServed`, `requestsFailed`). The router's own `400` and `404`, and injected faults, aren't logged. |
|
|
106
|
+
| `-e`, `-g`, `--dataset` | Environment, globals and datasets for every member, as for `mock run`. |
|
|
107
|
+
| `--no-history` | Record nothing. A `.sim.yaml` linked to a workspace otherwise records each start there; an unlinked one records only with `-w` and `--simulation`. |
|
|
108
|
+
|
|
109
|
+
The argument can also be a simulation id from a workspace: the members are
|
|
110
|
+
fetched and served locally. All members start before the port opens, so one
|
|
111
|
+
`listening` event means the whole simulation is up. A member that fails to
|
|
112
|
+
start stops the run with `Error: ...` and exit code 1. Ctrl+C stops everything.
|
|
@@ -73,9 +73,10 @@ answering "did my app's actual calls conform to the contract," not "does
|
|
|
73
73
|
this endpoint respond correctly." `--capture-only` skips the matching step
|
|
74
74
|
entirely and just exports what was captured as a new v3 collection,
|
|
75
75
|
organized by host — a way to bootstrap a collection from real traffic
|
|
76
|
-
rather than authoring one from scratch. Results
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
rather than authoring one from scratch. Results are published to the connected
|
|
77
|
+
workspace after each run, so the evidence of the run outlives the terminal
|
|
78
|
+
session; `--report-events=false` keeps a run local when it shouldn't be
|
|
79
|
+
recorded.
|
|
79
80
|
|
|
80
81
|
## Critical Rules
|
|
81
82
|
|
|
@@ -22,8 +22,7 @@ repo is already set up.
|
|
|
22
22
|
- Never invent a subcommand or a flag. Run `-h` first and believe it.
|
|
23
23
|
- Lint specs with `postman spec lint`, never `postman api …` — the API Builder
|
|
24
24
|
is deprecated in v12+ and the CLI prints no warning.
|
|
25
|
-
- Local commands need no login
|
|
26
|
-
workspace do. Don't force a login the task doesn't need.
|
|
25
|
+
- Local commands need no login.
|
|
27
26
|
- A missing `postman` binary means install it. Route to `postman-mcp-server`
|
|
28
27
|
only after an install has been attempted and actually failed.
|
|
29
28
|
- Never fabricate a workspace id, spec path, or collections directory. Report
|
|
@@ -31,11 +30,15 @@ repo is already set up.
|
|
|
31
30
|
- Never echo an API key or session token into output, logs, or summaries.
|
|
32
31
|
- "Present" is not "current": check the version and existing links before
|
|
33
32
|
setting anything up.
|
|
34
|
-
-
|
|
33
|
+
- Operate inside a repository, including a fresh repository for a new project.
|
|
34
|
+
Never scaffold the API implementation or a starter spec.
|
|
35
35
|
- Write no host-specific paths — the same `skills/` directory loads on every
|
|
36
36
|
route.
|
|
37
37
|
- Do not use `init` or `workspace create` to share or import a workspace that
|
|
38
38
|
already exists. Choose the direction of sync from the lifecycle table below.
|
|
39
|
+
- Before pulling, apply `api-discovery`'s owning-workspace-versus-dependency
|
|
40
|
+
distinction; finding a workspace does not by itself make it this
|
|
41
|
+
repository's workspace.
|
|
39
42
|
|
|
40
43
|
## Ask the CLI: `-h`
|
|
41
44
|
|
|
@@ -79,15 +82,16 @@ npm view postman-cli version
|
|
|
79
82
|
|
|
80
83
|
### 1.2 Install only if missing
|
|
81
84
|
|
|
82
|
-
**
|
|
85
|
+
**npm — all platforms, using Node's global package install:**
|
|
83
86
|
|
|
84
87
|
```bash
|
|
85
88
|
npm install -g postman-cli
|
|
86
89
|
```
|
|
87
90
|
|
|
88
|
-
**
|
|
89
|
-
|
|
90
|
-
|
|
91
|
+
**Platform installers — direct shell installs for macOS, Linux, WSL, and
|
|
92
|
+
Windows:** use the commands in
|
|
93
|
+
[reference/cli_installation.md](reference/cli_installation.md). Every route
|
|
94
|
+
puts `postman` on `PATH`.
|
|
91
95
|
|
|
92
96
|
**Updating a copy that already exists:** use the same route that installed it.
|
|
93
97
|
curl-installed binaries don't take `npm install -g` cleanly.
|
|
@@ -101,10 +105,10 @@ only thing that qualifies.
|
|
|
101
105
|
|
|
102
106
|
### 2.1 Authenticate only if this step needs it
|
|
103
107
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
+
`postman init` needs no normal login — init uses an agent-scoped session.
|
|
109
|
+
Do not log in before init. Authenticate only when the command you're about to
|
|
110
|
+
run operates on an existing workspace, such as listing, inspecting, pulling,
|
|
111
|
+
pushing, or changing access to one.
|
|
108
112
|
|
|
109
113
|
**With an API key — preferred, non-interactive:**
|
|
110
114
|
|
|
@@ -127,23 +131,27 @@ more.
|
|
|
127
131
|
Read `.postman/resources.yaml` for `localResources` and `workspace.id`, and
|
|
128
132
|
inspect the local `postman/` tree. When the user names an existing workspace or
|
|
129
133
|
asks to import, sync, or share one, use `workspace list --json` and `workspace
|
|
130
|
-
get <id> --elements --json` to confirm the workspace side.
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
134
|
+
get <id> --elements --json` to confirm the workspace side. Also establish
|
|
135
|
+
whether that workspace owns the service represented by this repository. Never
|
|
136
|
+
create a second workspace merely because this repository is not connected yet,
|
|
137
|
+
and never replace this repository's binding with another service's workspace.
|
|
138
|
+
|
|
139
|
+
Prefer filesystem-first work. For the current service, materialize its existing
|
|
140
|
+
workspace with `workspace pull <id>`, or create and bind one with `postman init
|
|
141
|
+
--json --visibility <personal|team>` when no workspace exists. For another
|
|
142
|
+
service, use `postman dependency add <type> <name-or-id>` as described in
|
|
143
|
+
`api-discovery`. Then inspect, edit, diff, and validate the version-controlled
|
|
144
|
+
files before any push.
|
|
137
145
|
|
|
138
146
|
| Existing state and intent | Use | Why |
|
|
139
147
|
| --- | --- | --- |
|
|
140
|
-
| No workspace exists;
|
|
141
|
-
|
|
|
142
|
-
|
|
|
143
|
-
|
|
|
148
|
+
| No workspace exists; create and bind one | `postman init --json --visibility <personal|team>` or `postman workspace create --visibility <value>` | Creates and binds the owning workspace; the init path also creates the git-native filesystem. |
|
|
149
|
+
| The current service's workspace exists; enable filesystem work in its repository | `postman workspace pull <workspace-id>` | Connects the owning workspace to the repository and materializes its entities under `postman/`. |
|
|
150
|
+
| The current service's workspace exists; record only the Git binding | `postman workspace connect-git <workspace-id> [path]` | Binds its repository without downloading its contents. |
|
|
151
|
+
| Another service's resource is needed here | `postman dependency add <type> <name-or-id>`; add `--workspace <workspace-id>` when resolving a name in a specific workspace | Declares and downloads only that collection, environment, or mock without rebinding this repository or pulling the other service's whole workspace. |
|
|
144
152
|
| Bound workspace; the workspace is authoritative | `postman workspace pull` | Refreshes local files from the connected workspace. |
|
|
145
|
-
| Bound workspace; local files are authoritative | `postman workspace diff --push-strategy default`, then `postman workspace push` |
|
|
146
|
-
| “Share this existing workspace with my team” and it is already team-accessible | Diff, then `postman workspace push` |
|
|
153
|
+
| Bound workspace; local files are authoritative | `postman workspace diff --push-strategy default`, then `postman workspace push` | Persists the local API context for future work and sharing with others by publishing creates/updates without deleting unmatched workspace entities. |
|
|
154
|
+
| “Share this existing workspace with my team” and it is already team-accessible | Diff, then `postman workspace push` | Persists local context in the existing workspace so teammates can share and build on it; `create` would make a duplicate. |
|
|
147
155
|
|
|
148
156
|
If “share” also requires changing a personal workspace's visibility or team
|
|
149
157
|
permissions, inspect its metadata first. `push` synchronizes entities; it does
|
|
@@ -162,15 +170,20 @@ deletions. Do not add `-y` merely to bypass a prompt.
|
|
|
162
170
|
environments. Downstream skills read that file and nothing else.
|
|
163
171
|
|
|
164
172
|
```bash
|
|
165
|
-
postman init --json --
|
|
166
|
-
postman init --json --visibility
|
|
173
|
+
postman init --json --visibility personal
|
|
174
|
+
postman init --json --visibility team
|
|
167
175
|
```
|
|
168
176
|
|
|
169
177
|
Use `--visibility` only when a new workspace is actually wanted. If the
|
|
170
|
-
workspace already exists, use `pull`
|
|
171
|
-
|
|
178
|
+
current service's workspace already exists, use `pull` from that service's
|
|
179
|
+
repository to enable the filesystem workflow. If the existing workspace
|
|
180
|
+
belongs to another service, use it as a dependency instead. Use `push` only
|
|
181
|
+
when publishing local changes to an already-bound workspace.
|
|
172
182
|
|
|
173
|
-
|
|
183
|
+
Without `--visibility`, interactive init prompts for the workspace step, while
|
|
184
|
+
`--json` skips that step because it may not prompt. Use `--visibility` when an
|
|
185
|
+
agent should create and bind a workspace non-interactively; omit it when a
|
|
186
|
+
local-only setup is intended.
|
|
174
187
|
|
|
175
188
|
**Read the payload, not stderr.** Take `bindings` and `exitCode` from the JSON.
|
|
176
189
|
Each binding reports a `source` of `inferred` or `none` — an inferred spec is a
|
|
@@ -187,8 +200,9 @@ written but the requested workspace was not created — it does *not* mean re-ru
|
|
|
187
200
|
- `postman --version` returned a real version.
|
|
188
201
|
- Auth is confirmed, or established as not required for this task.
|
|
189
202
|
- `.postman/resources.yaml` names a spec or a collections directory.
|
|
190
|
-
-
|
|
191
|
-
|
|
203
|
+
- When workspace creation was requested or the repository was already bound,
|
|
204
|
+
`workspace.id` is set to the owning workspace. A deliberately local-only
|
|
205
|
+
init may omit it.
|
|
192
206
|
- After `pull`, expected workspace entities exist under `postman/`. After
|
|
193
207
|
`push`, report created/updated entities and conflicts; do not claim a
|
|
194
208
|
workspace is shared unless its access level permits the intended teammates.
|
|
@@ -201,7 +215,7 @@ written but the requested workspace was not created — it does *not* mean re-ru
|
|
|
201
215
|
## Postman bootstrap
|
|
202
216
|
- **CLI**: <version> (latest: <version> | not checked)
|
|
203
217
|
- **Auth**: <api-key | browser | not required for this task>
|
|
204
|
-
- **Workspace**: <id |
|
|
218
|
+
- **Workspace**: <id | not requested | creation failed: reason>
|
|
205
219
|
- **Spec path**: <path (inferred | explicit) | none — user must create>
|
|
206
220
|
- **Collections dir**: <path | none — user must create>
|
|
207
221
|
```
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# Postman CLI Installation
|
|
2
2
|
|
|
3
|
-
A global install
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
A global install on `PATH`. npm works anywhere Node is available; the curl
|
|
4
|
+
installer covers macOS, Linux, and WSL; and the PowerShell installer covers
|
|
5
|
+
Windows. Whichever route put the binary there is the one to use again when
|
|
6
|
+
updating it — mixing routes leaves two `postman` binaries and a `PATH`
|
|
6
7
|
question.
|
|
7
8
|
|
|
8
9
|
## Install
|
|
@@ -37,15 +37,16 @@ answers it (and covers every collection in the repo in one pass); reach for
|
|
|
37
37
|
bare `collection lint` only when there's no workspace to fetch rules from
|
|
38
38
|
yet.
|
|
39
39
|
|
|
40
|
-
##
|
|
41
|
-
|
|
42
|
-
`postman workspace push -y`
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
40
|
+
## Persist and share context — only after merge
|
|
41
|
+
|
|
42
|
+
`postman workspace push -y` persists the merged repository's API context in
|
|
43
|
+
the workspace for future work and enables sharing it with others. It is the one
|
|
44
|
+
command in this skill that changes shared workspace state, so it belongs behind
|
|
45
|
+
a merge-to-main trigger, not a PR trigger. `-y` skips confirmation prompts a
|
|
46
|
+
non-interactive job can't answer. Leave `--no-prepare` off — the default
|
|
47
|
+
prepare step is what assigns real IDs to entities that are new since the last
|
|
48
|
+
push; skipping it because a run felt slow trades a few seconds for a push that
|
|
49
|
+
silently fails to create anything new.
|
|
49
50
|
|
|
50
51
|
`--push-strategy force-sync` mirrors the whole workspace, deleting any cloud
|
|
51
52
|
entity with no local counterpart — genuinely destructive, and not the
|
package/skills/datasets/SKILL.md
CHANGED
|
@@ -40,11 +40,12 @@ dataset: `list` takes a path or directory (its cloud form is
|
|
|
40
40
|
neither — it reads a driver JAR and touches no dataset at all.
|
|
41
41
|
|
|
42
42
|
There is no `dataset push` verb — but that does not mean local and cloud are
|
|
43
|
-
sealed off from each other. Datasets are a workspace entity, so
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
`dataset` verbs below are for
|
|
43
|
+
sealed off from each other. Datasets are a workspace entity, so `postman
|
|
44
|
+
workspace push` persists them in the bound workspace alongside collections,
|
|
45
|
+
environments and the rest, making that context available to future work and
|
|
46
|
+
for sharing with others. `postman workspace pull` brings them back down. Reach
|
|
47
|
+
for those when the whole repo should move; the `dataset` verbs below are for
|
|
48
|
+
working on one dataset in place.
|
|
48
49
|
|
|
49
50
|
## Core knowledge
|
|
50
51
|
|
|
@@ -80,7 +80,7 @@ execution and reporting. Takes the path positionally; a bad path fails with
|
|
|
80
80
|
| `-x, --suppress-exit-code` | Overrides the run's exit code. Defeats CI gating. |
|
|
81
81
|
| `--verbose` | Per-request detail: method, URL, assertions. |
|
|
82
82
|
| `--no-truncate` | Full output, no truncated long values. |
|
|
83
|
-
| `--no-report-events` |
|
|
83
|
+
| `--no-report-events` | Keep the run local instead of publishing results to the connected workspace. |
|
|
84
84
|
|
|
85
85
|
### BETA: dataset iteration
|
|
86
86
|
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: variables
|
|
3
|
+
description: How to parameterize a collection with variables and where each value belongs — a plain value goes in an environment or collection variable, a secret (token, password, API key) goes in the team's shared vault via `postman secret create` so its value never passes through the coding harness or lands in a committed file. Covers the variable scopes and their resolution order, reading and writing variables at runtime from pre-request and post-response scripts (`pm.environment`, `pm.collectionVariables`, `pm.variables`), and composing variables out of other variables. Use when the user asks where to put a base URL, token, or password, how to reference a secret without exposing it, how `{{variables}}` resolve, or how to set a value in a script. Covers `postman secret`.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Variables
|
|
7
|
+
|
|
8
|
+
A variable lets a request name a value — `{{base_url}}`, `{{authToken}}` —
|
|
9
|
+
instead of hardcoding it, so one collection runs against staging and
|
|
10
|
+
production and a secret never has to be typed into a request. The only real
|
|
11
|
+
decision is **where the value lives**, and it turns on one question: is it a
|
|
12
|
+
secret?
|
|
13
|
+
|
|
14
|
+
## Core foundations
|
|
15
|
+
1. One collection, many targets. Parameterize everything that changes between
|
|
16
|
+
environments so the same requests run everywhere — a diff in values, not in
|
|
17
|
+
requests.
|
|
18
|
+
2. Where a value lives is a security decision, not a convenience one. A plain
|
|
19
|
+
value is a variable; a secret belongs in the vault, nowhere else.
|
|
20
|
+
3. A secret's value should never reach this harness, the terminal, or a
|
|
21
|
+
committed file. `type: secret` only hides it in the UI — the value still
|
|
22
|
+
sits in clear text in the YAML. The vault is the only place it stays out of
|
|
23
|
+
the repo. (ref: postman secret command)
|
|
24
|
+
4. Resolution is narrowest-wins: `local (script) > data (iteration row) >
|
|
25
|
+
environment > collection > global`. This is what lets a collection ship a
|
|
26
|
+
default and an environment override just the few that differ.
|
|
27
|
+
5. Variables compose. A value can reference another (`usersUrl =
|
|
28
|
+
{{base_url}}/users`), and a script can set one at runtime to chain requests
|
|
29
|
+
(capture a token, use it on the next call). Resolution happens at send
|
|
30
|
+
time, not at definition time.
|
|
31
|
+
|
|
32
|
+
## Non-secret variables
|
|
33
|
+
|
|
34
|
+
A base URL, a non-sensitive id, a feature flag, a default page size — store it
|
|
35
|
+
as a variable and commit it. Reference it as `{{key}}` in a URL, header, query
|
|
36
|
+
param, or body. Scope picks the file:
|
|
37
|
+
|
|
38
|
+
- **Collection variable** — travels with the collection; use it for a default
|
|
39
|
+
that belongs to the API itself and rarely changes.
|
|
40
|
+
- **Environment variable** — swapped per target; use it for anything that
|
|
41
|
+
differs between staging and production. One file per environment, selected
|
|
42
|
+
at run time.
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
You can either directly edit into collection / environment file or use the cli commands to achieve the same.
|
|
46
|
+
```bash
|
|
47
|
+
postman environment new "Staging"
|
|
48
|
+
postman environment var set base_url https://staging.example.com \
|
|
49
|
+
--environment "postman/environments/Staging.environment.yaml"
|
|
50
|
+
postman environment lint postman/environments --fail-severity warning
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Set one at runtime from a script when you need to chain requests:
|
|
54
|
+
|
|
55
|
+
```javascript
|
|
56
|
+
// post-response: capture for later requests
|
|
57
|
+
pm.environment.set("authToken", pm.response.json().access_token);
|
|
58
|
+
// pre-request: read it back (any scope, resolution order applies)
|
|
59
|
+
const base = pm.variables.get("base_url");
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Use `pm.environment`/`pm.collectionVariables` to target a scope, `pm.variables`
|
|
63
|
+
to read across all of them, and `pm.variables.set` for a local value that
|
|
64
|
+
lives only for the current run.
|
|
65
|
+
|
|
66
|
+
## Secret keys
|
|
67
|
+
|
|
68
|
+
Passport is how people, services, and agents call APIs without ever holding
|
|
69
|
+
the secret. `postman secret` is the vault side of the same idea: it stores and
|
|
70
|
+
links secrets without putting their values in agent context or repository
|
|
71
|
+
files. Run `postman secret -h` for the supported vault operations and flags.
|
|
72
|
+
|
|
73
|
+
A bearer token, password, API key, client secret, or signing key goes in the
|
|
74
|
+
team's **shared vault**:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# interactive masked prompt (default when stdin is a terminal)
|
|
78
|
+
postman secret create STRIPE_API_KEY --workspace <workspaceId>
|
|
79
|
+
```
|
|
80
|
+
By default only the creator of secret can view the secret. Others in workspace can resolve the secret in their runs but can not see the secret value.
|
|
81
|
+
|
|
82
|
+
You then link the secret to an environment variable to use it in a request —
|
|
83
|
+
the CLI writes the link for you from `secret create`'s output:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
postman environment var set api_key --secret-id <secret-id> --vault-id <vault-id> \
|
|
87
|
+
--environment "postman/environments/Staging.environment.yaml"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The variable now points at the vault instead of holding a value; the file
|
|
91
|
+
carries only the reference, never the secret:
|
|
92
|
+
|
|
93
|
+
```yaml
|
|
94
|
+
values:
|
|
95
|
+
- key: api_key
|
|
96
|
+
enabled: true
|
|
97
|
+
type: secret
|
|
98
|
+
description: API key
|
|
99
|
+
secret: true
|
|
100
|
+
source:
|
|
101
|
+
provider: postman
|
|
102
|
+
postman:
|
|
103
|
+
type: cloud
|
|
104
|
+
secretId: <secret-id>
|
|
105
|
+
vaultId: <vault-id>
|
|
106
|
+
```
|