@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.
@@ -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 upload to Postman
77
- automatically after each run; `--report-events=false` skips that for a run
78
- that shouldn't be recorded.
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; only commands that reach the Postman
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
- - Wire up an existing repo only. Never scaffold a new API or a starter spec.
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
- **Preferred — npm, all platforms:**
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
- **Windows, or avoiding a global npm install:** use the platform installers in
89
- [reference/cli_installation.md](reference/cli_installation.md). Every route puts
90
- `postman` on `PATH`.
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
- Local commands need no login, and `postman init` is among them — its own help
105
- says *"No authentication, and safe in CI."* Skip this entirely unless the
106
- command you're about to run pulls or pushes an existing workspace, or shares
107
- one with a team.
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. Never create a
131
- second workspace merely because this repository is not connected yet.
132
-
133
- Prefer filesystem-first work: materialize an existing workspace with
134
- `workspace pull <id>`, or initialize local files with `postman init --no-cloud`
135
- when no workspace exists. Then inspect, edit, diff, and validate the
136
- version-controlled files before any push.
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; start locally | `postman init --json --no-cloud` | Creates the git-native filesystem without requiring login. |
141
- | No workspace exists; create and bind one | `postman workspace create --visibility <value>` or the explicit init creation path | Creation is the requested lifecycle event. |
142
- | Workspace exists; enable filesystem work | `postman workspace pull <workspace-id>` | Connects the workspace to the repository and materializes its entities under `postman/`. |
143
- | Workspace exists; record only the Git binding | `postman workspace connect-git <workspace-id> [path]` | Binds without downloading its contents. |
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` | Previews and publishes creates/updates without deleting unmatched workspace entities. |
146
- | “Share this existing workspace with my team” and it is already team-accessible | Diff, then `postman workspace push` | Publishes local contents to the existing workspace; `create` would make a duplicate. |
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 --no-cloud # local only, no workspace
166
- postman init --json --visibility personal # also create and bind a workspace
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` to enable the filesystem workflow;
171
- use `push` only when publishing local changes to an already-bound workspace.
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
- **The workspace step is interactive** without `--no-cloud` or `--visibility`.
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
- - `workspace.id` is set, or the run was deliberately local-only — `--no-cloud`
191
- leaves it empty and still exits 0, which is a pass, not a gap.
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 | none — local only>
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, on `PATH`, installed by one of three tools depending on
4
- platform. Whichever one put the binary there is the one to use again when
5
- updating it — mixing tools leaves two `postman` binaries and a `PATH`
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
- ## Push to workspace — only after merge
41
-
42
- `postman workspace push -y` is the one command in this skill that changes
43
- shared cloud state, so it belongs behind a merge-to-main trigger, not a PR
44
- trigger. `-y` skips confirmation prompts a non-interactive job can't answer.
45
- Leave `--no-prepare` off — the default prepare step is what assigns real IDs
46
- to entities that are new since the last push; skipping it because a run
47
- felt slow trades a few seconds for a push that silently fails to create
48
- anything new.
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
@@ -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
- `postman workspace push` syncs them to the bound workspace along with
45
- collections, environments and the rest, and `postman workspace pull` brings
46
- them back down. Reach for those when the whole repo should move; the
47
- `dataset` verbs below are for working on one dataset in place.
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` | Don't send analytics. `--report-events` exists for compatibility; analytics are on by default. |
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
+ ```