@postman/postman-plugin 0.1.1-rc.0 → 0.1.2-rc.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 +14 -2
- package/dist/cli.js +7 -1
- package/dist/hosts/index.js +2 -1
- package/dist/hosts/kimi.js +5 -2
- package/dist/hosts/pi.js +84 -0
- package/dist/pi-extension.js +27 -0
- package/dist/run.js +16 -10
- package/dist/source.js +3 -1
- package/hooks/session-start-context.md +11 -0
- package/mcp.pi.json +14 -0
- package/package.json +21 -6
- package/skills/ai-readiness/SKILL.md +50 -0
- package/skills/api-discovery/SKILL.md +135 -0
- package/skills/api-discovery/reference/orbit.md +101 -0
- package/skills/api-documentation/SKILL.md +34 -0
- package/skills/api-documentation/reference/rest-api-best-practices.md +47 -0
- package/skills/api-engineer/SKILL.md +29 -0
- package/skills/api-mocking/SKILL.md +141 -0
- package/skills/api-monitoring/SKILL.md +137 -0
- package/skills/api-testing/SKILL.md +103 -0
- package/skills/bootstrap/SKILL.md +216 -0
- package/skills/bootstrap/reference/cli_installation.md +58 -0
- package/skills/ci-integration/SKILL.md +121 -0
- package/skills/collection-schema-v3/SKILL.md +210 -0
- package/skills/collection-schema-v3/reference/environment.md +63 -0
- package/skills/collection-schema-v3/reference/other_protocols.md +86 -0
- package/skills/datasets/SKILL.md +323 -0
- package/skills/flows/SKILL.md +212 -0
- package/skills/flows/reference/flow_cli_flags.md +111 -0
- package/skills/performance-testing/SKILL.md +71 -0
- package/skills/postman-mcp-server/SKILL.md +71 -0
- package/skills/postman-mcp-server/references/docs.md +88 -0
- package/skills/postman-mcp-server/references/learn.md +73 -0
- package/skills/postman-mcp-server/references/mcp-limitations.md +38 -0
- package/skills/postman-mcp-server/references/mock.md +101 -0
- package/skills/postman-mcp-server/references/search.md +83 -0
- package/skills/postman-mcp-server/references/security.md +129 -0
- package/skills/postman-mcp-server/references/setup.md +141 -0
- package/skills/postman-mcp-server/references/sync.md +85 -0
- package/skills/postman-mcp-server/references/test.md +84 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Non-HTTP request schemas (v3)
|
|
2
|
+
|
|
3
|
+
Read this only when a collection actually contains one of these request
|
|
4
|
+
types — for the common case, the HTTP schema in the parent
|
|
5
|
+
[SKILL.md](../SKILL.md) is the one that applies.
|
|
6
|
+
|
|
7
|
+
## GraphQL request
|
|
8
|
+
|
|
9
|
+
- `$kind: "graphql-request"` — required.
|
|
10
|
+
- `url` — string.
|
|
11
|
+
- `order` — optional.
|
|
12
|
+
- `query` — string (the GraphQL query).
|
|
13
|
+
- `variables` — string (a YAML string containing a JSON object).
|
|
14
|
+
- `headers` — array of `{key, value, description?, disabled?}`.
|
|
15
|
+
- `auth` — `{type, credentials}`.
|
|
16
|
+
- `settings` — `{disabledSystemHeaders?}`.
|
|
17
|
+
- `scripts` — array of `{type: "beforeQuery"|"afterResponse", code, language}`.
|
|
18
|
+
|
|
19
|
+
## gRPC request
|
|
20
|
+
|
|
21
|
+
- `$kind: "grpc-request"` — required.
|
|
22
|
+
- `url` — string.
|
|
23
|
+
- `order` — optional.
|
|
24
|
+
- `methodPath` — string.
|
|
25
|
+
- `methodDescriptor` — string.
|
|
26
|
+
- `message` — `{content: string (JSON)}`.
|
|
27
|
+
- `metadata` — array of `{key, value, description?}`.
|
|
28
|
+
- `auth` — `{type, credentials}`.
|
|
29
|
+
- `settings` —
|
|
30
|
+
`{secureConnection?, strictSSL?, maxResponseMessageSize?, includeDefaultFields?, connectionTimeout?}`.
|
|
31
|
+
- `scripts` — array of `{type: "beforeInvoke"|"afterResponse", code, language}`.
|
|
32
|
+
|
|
33
|
+
## WebSocket request
|
|
34
|
+
|
|
35
|
+
- `$kind: "websocket-request"` — required.
|
|
36
|
+
- `url` — string.
|
|
37
|
+
- `order` — optional.
|
|
38
|
+
- `headers` — array of `{key, value, description?, disabled?}`.
|
|
39
|
+
- `queryParams` — array of `{key, value, description?, disabled?}`.
|
|
40
|
+
- `settings` — `{handshakeTimeout?, retryCount?, retryDelay?, maxPayload?, strictSSL?}`.
|
|
41
|
+
|
|
42
|
+
## Socket.IO request
|
|
43
|
+
|
|
44
|
+
- `$kind: "socket.io-request"` — required.
|
|
45
|
+
- `url` — string.
|
|
46
|
+
- `order` — optional.
|
|
47
|
+
- `headers` — array of `{key, value}`.
|
|
48
|
+
- `queryParams` — array of `{key, value}`.
|
|
49
|
+
- `events` — array of `{name, description?, subscribeOnConnect: boolean}`.
|
|
50
|
+
- `settings` — `{version?, path?, handshakeTimeout?, retryCount?, retryDelay?, strictSSL?}`.
|
|
51
|
+
|
|
52
|
+
## MQTT request
|
|
53
|
+
|
|
54
|
+
- `$kind: "mqtt-request"` — required.
|
|
55
|
+
- `url` — string.
|
|
56
|
+
- `order` — optional.
|
|
57
|
+
- `clientId` — string.
|
|
58
|
+
- `version` — `4 | 5`.
|
|
59
|
+
- `topics` — array of
|
|
60
|
+
`{name, qos: 0|1|2, subscribe: boolean, description?, settings: {noLocal?, retainAsPublished?, retainHandling?, subscriptionIdentifier?}}`.
|
|
61
|
+
- `lastWill` — `{topic, payload, qos, retain, type: "text"|"json", properties: {messageExpiryInterval?, contentType?}}`.
|
|
62
|
+
- `properties` —
|
|
63
|
+
`{sessionExpiryInterval?, receiveMaximum?, maximumPacketSize?, requestResponseInformation?, userProperties: [{key, value}]}`.
|
|
64
|
+
- `settings` — `{cleanSession?, keepAlive?, autoReconnect?, connectionTimeout?, strictSSL?}`.
|
|
65
|
+
|
|
66
|
+
## MCP request
|
|
67
|
+
|
|
68
|
+
- `$kind: "mcp-request"` — required.
|
|
69
|
+
- `transport` — `"sse" | "stdio"`.
|
|
70
|
+
- `order` — optional.
|
|
71
|
+
- SSE shape: `{url, headers?, message, auth?, settings: {strictSSL?, requestTimeout?, sessionTimeout?}}`.
|
|
72
|
+
- STDIO shape: `{command, env: [{key, value}], message, auth?, settings: {requestTimeout?}}`.
|
|
73
|
+
|
|
74
|
+
## LLM request
|
|
75
|
+
|
|
76
|
+
- `$kind: "llm-request"` — required.
|
|
77
|
+
- `url` — string.
|
|
78
|
+
- `order` — optional.
|
|
79
|
+
- `config` — `{model, provider}`.
|
|
80
|
+
- `userPrompts` — array of `{id, value, timestamp, active, type: "text"}`.
|
|
81
|
+
- `systemPrompts` — array of `{id, value, timestamp, active, type: "text"}`.
|
|
82
|
+
- `mcpConfig` — optional string (JSON config).
|
|
83
|
+
- `enabledTools` — optional array of strings.
|
|
84
|
+
- `auth` — `{type, credentials}`.
|
|
85
|
+
- `settings` —
|
|
86
|
+
`{temperature?, maxToken?, streamResponse?, responseFormatJSON?, topP?, presencePenalty?, frequencyPenalty?, maxSteps?, streamTools?}`.
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: datasets
|
|
3
|
+
description: Query CSV and JSON files, spreadsheet exports, and live databases (MySQL, PostgreSQL, SQL Server, or anything with a JDBC driver JAR) as one SQL surface; join across them; save a query as a named view so it can be rerun without re-pasting the SQL; then drive a collection run one iteration per row — feeding it the rows a query returns instead of a hardcoded data file — or read rows from scripts via `pm.datasets()`. Use when the user wants to run or loop a collection over rows of test data, parameterize a run from a CSV or spreadsheet or database table, query or join data across files and tables, save or rerun a query without pasting it again, use a query's result rows as the input for a run in place of hardcoded JSON or a data file, point Postman at a JDBC driver, work out where database credentials get stored, or names a Postman dataset or view. Covers `postman dataset` (`source`, `view`, `query`, `jdbc`) and `--iteration-data-dataset`/`--iteration-data-view`/`--dataset` on `collection run`.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Datasets
|
|
7
|
+
|
|
8
|
+
## Required CLI version
|
|
9
|
+
|
|
10
|
+
This skill documents the dataset commands as they behave **after**
|
|
11
|
+
postman-cli#1323 (AUTO-987, the spurious `No authorization data found`
|
|
12
|
+
notice) and postman-cli#1340 (AUTO-999/AUTO-998, one datasource per
|
|
13
|
+
worksheet plus the help-text fixes). Both are needed; 1.62.0 has neither.
|
|
14
|
+
Check with `postman --version` before trusting the worksheet and
|
|
15
|
+
auth-notice rules below, and on an older CLI expect `source add --file
|
|
16
|
+
book.xlsx` to add a workbook as a single unqueryable source (in a cloud
|
|
17
|
+
dataset too), `source update --file book.xlsx` to be accepted and rewrite the
|
|
18
|
+
source to `format: csv`, and every logged-out `--iteration-data-dataset` run
|
|
19
|
+
to print the notice.
|
|
20
|
+
|
|
21
|
+
## Overview
|
|
22
|
+
|
|
23
|
+
A dataset is a Postman entity that names one or more *datasources* and
|
|
24
|
+
presents them as SQL tables. It lives either in a Postman workspace or in the
|
|
25
|
+
repository, and the same commands work on both — with one carve-out, a
|
|
26
|
+
spreadsheet source, covered below. It is not a data file — it is
|
|
27
|
+
a layer over data files and databases, and the value is in that layer:
|
|
28
|
+
heterogeneous
|
|
29
|
+
sources (a CSV and a Postgres table) become joinable in one query, and a
|
|
30
|
+
saved *view* turns a query into a named, reusable result set that a
|
|
31
|
+
collection run can iterate.
|
|
32
|
+
|
|
33
|
+
Local and cloud are the same commands. Every verb that acts on an *existing*
|
|
34
|
+
dataset — `get`, `query`, `delete`, and every `source` and `view`
|
|
35
|
+
subcommand — takes either a `.dataset.yaml` path or a cloud dataset id and
|
|
36
|
+
routes accordingly. Two verbs name a location instead of an existing
|
|
37
|
+
dataset: `list` takes a path or directory (its cloud form is
|
|
38
|
+
`-w <workspaceId>`), and `create` takes the path to write (its cloud form is
|
|
39
|
+
`-w` with no path, since the id does not exist yet). `jdbc inspect` takes
|
|
40
|
+
neither — it reads a driver JAR and touches no dataset at all.
|
|
41
|
+
|
|
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.
|
|
48
|
+
|
|
49
|
+
## Core knowledge
|
|
50
|
+
|
|
51
|
+
- **Datasets are the current way to drive a run from data.** They supersede
|
|
52
|
+
passing a flat file with `-d`/`--iteration-data`: a dataset gives the same
|
|
53
|
+
row-per-iteration behaviour, and on top of it SQL to filter and shape rows,
|
|
54
|
+
joins across several sources, a live database instead of an export, named
|
|
55
|
+
views that can be rerun, and `pm.datasets()` access from scripts. Reach for
|
|
56
|
+
a dataset by default when someone wants to run a collection over rows of
|
|
57
|
+
data; `-d` remains available for a one-off file and stays the lighter option
|
|
58
|
+
when nothing more is wanted.
|
|
59
|
+
|
|
60
|
+
- **A spreadsheet becomes one source per worksheet, not one source — and
|
|
61
|
+
only in a local dataset.** The engine reads Excel and OpenDocument
|
|
62
|
+
workbooks (`xlsx`, `xls`, `ods`) as well as CSV and JSON, and
|
|
63
|
+
`source add --file book.xlsx` enumerates the sheets and adds each as its own
|
|
64
|
+
datasource — matching what the Postman app does. There is no flag for
|
|
65
|
+
picking a sheet, by design. Three boundaries come before anything else:
|
|
66
|
+
|
|
67
|
+
- **Local datasets only.** Adding a workbook to a *cloud* dataset is
|
|
68
|
+
refused with `SPREADSHEET_CLOUD_UNSUPPORTED`, with or without `--upload`:
|
|
69
|
+
a cloud add posts one datasource with no worksheet selector and the cloud
|
|
70
|
+
service is never handed the bytes to fan the workbook out itself, so it
|
|
71
|
+
would persist exactly the unqueryable source the local path exists to
|
|
72
|
+
prevent. CSV and JSON work on both. This is the carve-out to
|
|
73
|
+
"local and cloud are the same commands" — put the workbook in a local
|
|
74
|
+
`.dataset.yaml`.
|
|
75
|
+
- **`xlsx`, `xls` and `ods` only.** `.xlsm`, `.xlsb` and `.numbers` are
|
|
76
|
+
unmistakably workbooks that the engine cannot read, so extension
|
|
77
|
+
inference refuses them with `WORKBOOK_FORMAT_UNSUPPORTED` rather than
|
|
78
|
+
letting them fall through to the `csv` default and write a source that
|
|
79
|
+
fails every query. Re-save as `.xlsx`, or pass `--format csv` only if the
|
|
80
|
+
file really is delimited text.
|
|
81
|
+
- **`-n` is optional for a workbook, and ignored.** It is required for
|
|
82
|
+
every other source kind, but worksheet sources are named after their
|
|
83
|
+
sheets, so a `-n` passed here changes nothing and earns a
|
|
84
|
+
`NAME_UNUSED_FOR_SPREADSHEET` warning.
|
|
85
|
+
|
|
86
|
+
Each source is named `source_<sheet>`, with anything outside
|
|
87
|
+
`[a-zA-Z0-9_]` replaced by `_`, and `_2`/`_3` appended on collision —
|
|
88
|
+
collision being judged on the engine's *table* key rather than on the
|
|
89
|
+
literal name, so two sheets that normalise onto one table are given
|
|
90
|
+
distinct names instead of registering one table twice and failing every
|
|
91
|
+
query on the dataset. A workbook with People, Orders and "Sales Q3 2026"
|
|
92
|
+
therefore gives `source_People`, `source_Orders` and
|
|
93
|
+
`source_Sales_Q3_2026`. The `-n` you passed does **not** appear in them —
|
|
94
|
+
the scheme matches the Postman app (and DCS server-side), so a workbook
|
|
95
|
+
added from the CLI and the same one added from the app produce identical
|
|
96
|
+
source names and survive a push/pull round trip.
|
|
97
|
+
|
|
98
|
+
Those are *source* names, and a source name is not always a table name.
|
|
99
|
+
**Take the queryable name from the command's own output instead of deriving
|
|
100
|
+
it.** `source add` prints a line per sheet —
|
|
101
|
+
`"source_People" (id: …) from worksheet "People"` — and appends
|
|
102
|
+
`, queryable as "<table>"` whenever the table differs, so a `売上` sheet is
|
|
103
|
+
reported as `source___`, queryable as `source`, and `FROM source` is the
|
|
104
|
+
query. Under `--json` the same thing arrives as `sources[]`, one
|
|
105
|
+
`{id, name, worksheet, table}` entry per worksheet and present for every
|
|
106
|
+
workbook add however many sheets it found; `table` is the field a `FROM`
|
|
107
|
+
clause takes. Still don't copy `name` into a `FROM` clause verbatim, and
|
|
108
|
+
note that a `source_` prefix is correct here and wrong for a source you
|
|
109
|
+
named yourself, so do not carry the habit across.
|
|
110
|
+
|
|
111
|
+
**`source update` cannot make a worksheet source, and now refuses to try.**
|
|
112
|
+
Both halves are hard refusals with a code, and nothing is written:
|
|
113
|
+
`--file <workbook>` fails `SPREADSHEET_FILE_NOT_UPDATABLE` (`.xlsm`,
|
|
114
|
+
`.xlsb` and `.numbers` included) and `--format xlsx|xls|ods` fails
|
|
115
|
+
`SPREADSHEET_FORMAT_NOT_UPDATABLE`, because the command patches `format`
|
|
116
|
+
and `location` field-wise and has no way to pin a worksheet. What is still
|
|
117
|
+
*allowed* and still destructive is `update --file other.csv` on a source
|
|
118
|
+
that already has a worksheet: that patch carries no `source_options`, so
|
|
119
|
+
the stale `spreadsheet.worksheet` selector stays pinned to a file with no
|
|
120
|
+
worksheets and the source stops being queryable (AUTO-1000). Remove the
|
|
121
|
+
source and re-add the workbook with `source add`.
|
|
122
|
+
|
|
123
|
+
- **`--format` is not validated.** Its help text lists the real formats, but
|
|
124
|
+
the flag accepts any string and writes it straight into the manifest, so a
|
|
125
|
+
typo becomes a source that fails only later at query time. Pass it only to
|
|
126
|
+
override inference deliberately; otherwise let the file extension speak.
|
|
127
|
+
- **A datasource's table name is its `name` *normalised*, not its `name`.**
|
|
128
|
+
Before exposing a source as a table the engine lowercases the name,
|
|
129
|
+
collapses every run of `_` to a single `_`, and strips leading and trailing
|
|
130
|
+
`_`. So `-n users` really is `FROM users`, but `-n Sales__Q3_` is
|
|
131
|
+
`FROM sales_q3` — and `FROM Sales__Q3_`, the name you passed and the name
|
|
132
|
+
the CLI echoes back, fails `SQL_UNKNOWN_TABLE`. Case alone is safe (SQL
|
|
133
|
+
identifiers are case-insensitive, so `FROM MixedCase` still finds
|
|
134
|
+
`mixedcase`); underscore runs and edge underscores are not. Keep source
|
|
135
|
+
names already-normalised and the two can never diverge. A workbook add
|
|
136
|
+
reports each sheet's table itself (`queryable as …`, or `sources[].table`
|
|
137
|
+
under `--json`); for anything else, on the federated path
|
|
138
|
+
`SELECT name FROM sqlite_master WHERE type='table'` lists the real ones.
|
|
139
|
+
**The CLI's own `-h` examples say `FROM source_users`, and they are
|
|
140
|
+
wrong** — there is no `source_` prefixing for a source you named
|
|
141
|
+
yourself, and `source_users` fails `SQL_UNKNOWN_TABLE`. Trust the normalised source
|
|
142
|
+
name, not the example text.
|
|
143
|
+
- **Federated vs native is the central query decision.** With no `--source`,
|
|
144
|
+
the query runs through a federated SQLite layer that can join across every
|
|
145
|
+
*federatable* source in the dataset — which is all of them except JDBC, per
|
|
146
|
+
the next rule. With `--source <name>`, it is sent to that one
|
|
147
|
+
datasource in *its own SQL dialect* — which is the only thing that works
|
|
148
|
+
for JDBC sources, and what you want for dialect-specific SQL
|
|
149
|
+
(`now() - interval '1 day'`). `dataset query -s` and
|
|
150
|
+
`dataset view create -s` take the same reference. They are different
|
|
151
|
+
execution paths, not fallbacks for each other — adding or dropping
|
|
152
|
+
`--source` to make a failing query work changes what the query *means*.
|
|
153
|
+
- **JDBC is the one source type that cannot federate.** A native
|
|
154
|
+
`--type mysql|postgresql|sqlserver` source *does* join against a CSV in one
|
|
155
|
+
federated query, which is the main reason to build a mixed dataset. A
|
|
156
|
+
`--type jdbc` source does not appear in the federated layer at all: query
|
|
157
|
+
it without `--source` and it fails `SQL_UNKNOWN_TABLE`, exactly as a
|
|
158
|
+
misspelled table would. So a JDBC source cannot be joined to anything —
|
|
159
|
+
if you need that join, add the database as its native type instead.
|
|
160
|
+
- **Local does not mean free, and the plan gate keys off source type, not
|
|
161
|
+
dataset location.** CSV/JSON sources run fully offline, logged out. Any
|
|
162
|
+
*database* source — including one inside a purely local YAML — forces
|
|
163
|
+
authentication and an entitlement check: MySQL and PostgreSQL need a paid
|
|
164
|
+
plan, and **JDBC and SQL Server need Enterprise**
|
|
165
|
+
(`… data sources require an Enterprise plan.`, HTTP 402).
|
|
166
|
+
- **A view's result set is iteration data.** `collection run
|
|
167
|
+
--iteration-data-dataset <pathOrId> --iteration-data-view <nameOrId>`
|
|
168
|
+
runs one iteration per row, with each column bound as a variable
|
|
169
|
+
(`{{name}}`). Both flags are required together, and the pair is mutually
|
|
170
|
+
exclusive with `-d/--iteration-data`.
|
|
171
|
+
- **On a dataset run, `No authorization data found` means a source really
|
|
172
|
+
does need auth.** A file-backed dataset needs none, and a logged-out run
|
|
173
|
+
over one is silent. So if that line appears on an
|
|
174
|
+
`--iteration-data-dataset` run, read it as signal: a **database** source is
|
|
175
|
+
in play — `jdbc`, `mysql`, `postgres`/`postgresql` or `sqlserver`, and a
|
|
176
|
+
`postmancloudfile` source is *not* one of those and does not trigger it —
|
|
177
|
+
or you passed a cloud dataset id or a cloud collection, or the manifest
|
|
178
|
+
could not be read, those last three all landing on the same fail-closed
|
|
179
|
+
branch. What it is *not* is a verdict on the run — a plain
|
|
180
|
+
`collection run` with no dataset flags still prints it whenever you are
|
|
181
|
+
logged out, because it comes from the run command rather than anything
|
|
182
|
+
dataset-related.
|
|
183
|
+
- **`--dataset <pathOrDir>` is the other consumption path** — repeatable,
|
|
184
|
+
and it exposes datasets to scripts as `pm.datasets(<id>)` rather than
|
|
185
|
+
driving iterations. Resolution is lazy: a run that never calls
|
|
186
|
+
`pm.datasets` parses nothing and needs no auth. An unparseable YAML is
|
|
187
|
+
skipped with a `[pm.datasets] skipped …` warning, not a failed run — so a
|
|
188
|
+
silently absent dataset looks like a script bug.
|
|
189
|
+
- **Query parameters are positional.** `$1, $2` in the SQL, `-p` values in
|
|
190
|
+
order. Views can be parameterized too, but a parameterized view **cannot**
|
|
191
|
+
drive iteration data — `collection run` has nowhere to pass `-p`, and it
|
|
192
|
+
fails as an opaque execution error. Keep iteration views parameter-free.
|
|
193
|
+
- **Dataset commands never touch `.postman/resources.yaml`.** Unlike mocks,
|
|
194
|
+
there is no repo-level registry entry to commit or clean up — the
|
|
195
|
+
`.dataset.yaml` and its `data_dir` are the whole artifact.
|
|
196
|
+
- **`data_dir` is not only your data.** The local engine writes its own state
|
|
197
|
+
in there next to the copied files — `data.db`, `meta.db`, `daemon.log`,
|
|
198
|
+
`config/`, and a uuid-named directory. Commit the manifest and the source
|
|
199
|
+
files; ignore the rest, or the repo starts carrying a query cache and a log.
|
|
200
|
+
`daemon.log` is also the first place to look when the engine itself, rather
|
|
201
|
+
than a query, is what failed.
|
|
202
|
+
|
|
203
|
+
## Process
|
|
204
|
+
|
|
205
|
+
1. **Scaffold.** `postman dataset create ./postman/datasets/NAME/NAME.dataset.yaml
|
|
206
|
+
--name "NAME"` writes a four-line manifest with a generated id and
|
|
207
|
+
`data_dir: .resources`. The cloud form is `create --name "NAME" -w <workspaceId>`
|
|
208
|
+
with no path.
|
|
209
|
+
2. **Attach sources.** `postman dataset source add -d <dataset> -n <table>
|
|
210
|
+
--file ./users.csv` **copies** the file into `data_dir` — pass
|
|
211
|
+
`--ref-only` to reference it in place instead — but note it records an
|
|
212
|
+
**absolute** path, so a `--ref-only` dataset is machine-local and does not
|
|
213
|
+
survive being committed and cloned elsewhere. Extensions
|
|
214
|
+
pick the format only when `--format` is absent; contents are never
|
|
215
|
+
sniffed, so a `.txt` holding JSON needs `--format json`. For a cloud
|
|
216
|
+
dataset, `--file` alone registers a *local-filesystem* source read by the
|
|
217
|
+
local engine; `--upload` is what actually puts the data in the cloud.
|
|
218
|
+
Either way a cloud dataset takes csv and json only — a workbook is refused
|
|
219
|
+
there.
|
|
220
|
+
3. **For a *JDBC* source, start from `jdbc inspect`.**
|
|
221
|
+
`postman dataset jdbc inspect ./drivers/pg.jar` maps straight onto the
|
|
222
|
+
`source add` flags: `suggestedUrlTemplate` → `--url-template`,
|
|
223
|
+
`templateVariables` → `--var`, `connectionProperties` → `--prop`,
|
|
224
|
+
`driverClass` → `--driver-class`. A second source on the same database
|
|
225
|
+
reuses all of it with `--from-source <name>`. A connection test runs
|
|
226
|
+
before the write, so a JDBC source that cannot connect is never persisted
|
|
227
|
+
(`--no-test` opts out). A native `--type mysql|postgresql|sqlserver`
|
|
228
|
+
source needs none of this — no driver JAR, no inspect step, just
|
|
229
|
+
`--host/--port/--database/--user/--password` — and it is **not**
|
|
230
|
+
connection-tested before the write, so run `source test` yourself after
|
|
231
|
+
adding one.
|
|
232
|
+
4. **Explore with ad-hoc SQL before saving anything.**
|
|
233
|
+
`postman dataset query <dataset> -q "SELECT …"`. Get the query right
|
|
234
|
+
here — a view is just a query you have already proven.
|
|
235
|
+
5. **Save the query as a view.** `postman dataset view create -d <dataset>
|
|
236
|
+
-n "Active" -q "SELECT …"`, then `view run "Active" -d <dataset>` to
|
|
237
|
+
confirm the rows. This is the step that makes the dataset usable by a
|
|
238
|
+
run.
|
|
239
|
+
6. **Drive the run.** `postman collection run <collection>
|
|
240
|
+
--iteration-data-dataset <dataset> --iteration-data-view "Active"`.
|
|
241
|
+
Confirm the iteration count matches the row count — that is the only
|
|
242
|
+
proof the wiring works.
|
|
243
|
+
|
|
244
|
+
## Critical rules
|
|
245
|
+
|
|
246
|
+
1. **Secrets are only avoidable on the JDBC path, and that decides which
|
|
247
|
+
source type to use.** A credential passed as a **literal** lands in three
|
|
248
|
+
places: `ps` output, shell history, **and clear text in the dataset YAML**
|
|
249
|
+
(or the cloud request body). The CLI warns about exactly those three, and
|
|
250
|
+
only for literals. What differs by source type is whether there is an
|
|
251
|
+
alternative:
|
|
252
|
+
- **JDBC (`--var`, `--prop`): yes, and it avoids all three.**
|
|
253
|
+
`--var name=vault:<vaultId>/<secretId>` stores a `{$vaultId,$secretId}`
|
|
254
|
+
pointer and resolves it at query time, so the secret itself reaches none
|
|
255
|
+
of the three — only the reference travels through argv. `--vars-file`
|
|
256
|
+
reads the same values from a JSON file and `--vars-file -` from stdin,
|
|
257
|
+
which is the one way to keep a value out of `ps` and shell history; it
|
|
258
|
+
accepts vault refs too, and a *literal* passed that way still lands in
|
|
259
|
+
the YAML in clear text. Local Vault secrets are not supported — Shared
|
|
260
|
+
Vault only. A literal secret in `--url-template` is rejected outright: a
|
|
261
|
+
literal has no `{{name}}` to route through `--var`, so nothing could
|
|
262
|
+
mask it.
|
|
263
|
+
- **Native `--type mysql|postgresql|sqlserver` (`--user`, `--password`):
|
|
264
|
+
no.** The CLI says so on every write —
|
|
265
|
+
`Secret references for database credentials are not yet supported by
|
|
266
|
+
Postman CLI.` There is no vault form of these flags. The credentials
|
|
267
|
+
land in the YAML in clear text or the source does not exist.
|
|
268
|
+
|
|
269
|
+
So when credentials must not sit in a committed file, reach for
|
|
270
|
+
`--type jdbc` with Vault refs rather than the native type for the same
|
|
271
|
+
database. Otherwise treat that YAML as a secret-bearing file and keep it
|
|
272
|
+
out of version control.
|
|
273
|
+
2. **"The dataset operation failed with a server error. Please retry." is
|
|
274
|
+
usually not a server error and retrying will not help.** It is the
|
|
275
|
+
generic wrapper over engine errors, including your SQL being wrong.
|
|
276
|
+
Re-run with `--debug` to get the real code — `engineCode=SQL_UNKNOWN_TABLE`
|
|
277
|
+
for a bad table name, and so on. Read that before changing anything.
|
|
278
|
+
3. **When a query fails, isolate the layer with
|
|
279
|
+
`postman dataset source test -d <dataset> -n <source>`.** It opens and
|
|
280
|
+
closes a real connection using the stored config, resolving Vault
|
|
281
|
+
references the way a query would, which separates "the source is broken"
|
|
282
|
+
from "the SQL is wrong". File and URL sources have no connection and
|
|
283
|
+
report `SOURCE_NOT_TESTABLE` — that is the expected answer, not a fault.
|
|
284
|
+
4. **`--dataset` on a cloud collection does not scope access.** A script can
|
|
285
|
+
call `pm.datasets(<anyId>)` for any dataset the logged-in session can
|
|
286
|
+
read. Only run collections you trust against a logged-in cloud session.
|
|
287
|
+
5. **`dataset delete` is permanent and deliberately asymmetric** — it
|
|
288
|
+
removes the manifest but preserves the source files, because references
|
|
289
|
+
can cross directory boundaries. An empty `data_dir` is removed unless
|
|
290
|
+
`--keep-resources` is passed. Confirm before running it on a cloud id,
|
|
291
|
+
where there is no file left behind to recover from.
|
|
292
|
+
6. **Pass `--json` when parsing.** Both success and failure go to stdout, so
|
|
293
|
+
`--json 2>/dev/null | jq .` works either way, and failures carry a stable
|
|
294
|
+
`error.code` (`CONNECTION_FAILED`, `DRIVER_CLASS_AMBIGUOUS`,
|
|
295
|
+
`CONFIG_VALUE_MISSING`, …) plus `remediation`. Branch on the code, never
|
|
296
|
+
on the prose.
|
|
297
|
+
|
|
298
|
+
## Anti-patterns
|
|
299
|
+
|
|
300
|
+
- **Don't add a database source to make a demo "more realistic."** It
|
|
301
|
+
converts a zero-setup offline dataset into one that needs login, a paid
|
|
302
|
+
plan, network reachability, and (for JDBC/SQL Server) Enterprise. Use CSV
|
|
303
|
+
unless the live data is the point.
|
|
304
|
+
- **Don't run `postman dataset list` with no arguments** expecting the local
|
|
305
|
+
datasets. Bare `list` is the *cloud* form and errors without `-w` outside
|
|
306
|
+
a Postman-managed project; pass a path or directory for local ones.
|
|
307
|
+
- **Don't hand-edit `.dataset.yaml` to add a source.** `source add` runs the
|
|
308
|
+
connection test (JDBC), id generation, and secret validation that a
|
|
309
|
+
hand-edited entry skips — and the resolver re-inspects every YAML
|
|
310
|
+
precisely so a hand-edited file cannot bypass the source gate.
|
|
311
|
+
|
|
312
|
+
## Verification
|
|
313
|
+
|
|
314
|
+
A dataset is not working because `create` and `source add` exited 0 — those
|
|
315
|
+
prove only that the write went through: a manifest locally, a workspace
|
|
316
|
+
entity in the cloud, and on the JDBC path a connection that opened, unless
|
|
317
|
+
`--no-test` skipped that test. None of it proves a query returns rows. Run an actual query and state
|
|
318
|
+
the row count and columns you got back. For a run, state the iteration count
|
|
319
|
+
and confirm it equals the view's row count; three rows producing one
|
|
320
|
+
iteration means the view, not the collection, is what to look at. Say which
|
|
321
|
+
execution path ran (federated or `--source` native) and whether the dataset
|
|
322
|
+
was local or cloud — that determines whether the numbers reflect live data
|
|
323
|
+
or a copied snapshot in `data_dir`.
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: flows
|
|
3
|
+
description: Runs, deploys, and debugs Postman Flows from the command line — executing a flow file locally, triggering a deployed flow over its webhook, deploying one so it becomes callable, and tracing a failed run to the block that broke. Use when the user names a flow and an action ("run the Checkout flow", "deploy this flow", "why did that flow run fail", "what flows do I have"). Covers `postman flows list`, `run`, `trigger`, `deploy`, `update`, `list-runs`, and `get-run`.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Postman Flows
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Listing flows, running them, deploying them so they become callable, and
|
|
11
|
+
tracing a failed run to the block that caused it — all through
|
|
12
|
+
`postman flows`.
|
|
13
|
+
|
|
14
|
+
## Core knowledge
|
|
15
|
+
|
|
16
|
+
A flow is a graph of blocks, not a script. That single fact drives the rest of
|
|
17
|
+
this skill: a flow has two independent execution paths, and its HTTP response
|
|
18
|
+
describes one block rather than the whole graph, so debugging takes a
|
|
19
|
+
different command than running.
|
|
20
|
+
|
|
21
|
+
### Local file vs deployed artifact
|
|
22
|
+
|
|
23
|
+
`run` and `trigger` are not two ways to execute one flow. Postman Flows has
|
|
24
|
+
two Native Git modes, and they are isolated from each other:
|
|
25
|
+
|
|
26
|
+
- **Cloud View** (the default) syncs flows to Postman Cloud, which is what
|
|
27
|
+
makes them shareable and **deployable** — so Cloud View is the only side
|
|
28
|
+
`deploy`, `trigger`, `update`, `list-runs` and `get-run` ever address.
|
|
29
|
+
- **Local View** stores flows as JSON in a local Git repo, updated as they are
|
|
30
|
+
edited. Those flows **cannot be shared or deployed**, have no snapshots, and
|
|
31
|
+
are isolated from the flows in Cloud View.
|
|
32
|
+
|
|
33
|
+
| | `flows run <path>` | `flows trigger <flowId>` |
|
|
34
|
+
| --- | --- | --- |
|
|
35
|
+
| Executes | a flow JSON file on this machine | the cloud-deployed flow, via its webhook |
|
|
36
|
+
| Returns | status, output, test results, exit code | Run ID + HTTP status + response body |
|
|
37
|
+
| Observability | own stdout, `--output`, `--reporters` | `get-run`, per block |
|
|
38
|
+
| Environment file | `-e/--environment` | not supported |
|
|
39
|
+
|
|
40
|
+
`run` exits nonzero on failure, which is what lets a CI job gate on it.
|
|
41
|
+
`trigger` goes through the real webhook URL, so it exercises the deployed path
|
|
42
|
+
end-to-end — auth and trigger configuration included — and registers a cloud
|
|
43
|
+
run that `get-run` can explain block by block.
|
|
44
|
+
|
|
45
|
+
`postman init` scaffolds `postman/flows/`, and Postman's `flows run` examples
|
|
46
|
+
use that path. Note what puts files there: the Git-connected Flows experience
|
|
47
|
+
is **desktop-app only**, so `postman/flows/*.json` is written by the desktop
|
|
48
|
+
app's Local View, not by the CLI — `workspace push`/`pull` carry no flows
|
|
49
|
+
handling whatever else they sync. Don't tell a user to `workspace pull` to
|
|
50
|
+
obtain a flow file.
|
|
51
|
+
|
|
52
|
+
### What deploying buys, and what it requires
|
|
53
|
+
|
|
54
|
+
Deploying puts the flow in Postman's cloud and attaches an HTTP trigger, which
|
|
55
|
+
is what makes it reachable by schedules, webhooks, third-party apps, and other
|
|
56
|
+
APIs — the flow stops being something a human opens and becomes callable
|
|
57
|
+
infrastructure.
|
|
58
|
+
|
|
59
|
+
Three preconditions sit outside the CLI, so no flag or retry satisfies them:
|
|
60
|
+
the flow must be in Cloud View, its Start block must be configured with an API
|
|
61
|
+
request trigger, and its canvas must have a Response block. Check these before
|
|
62
|
+
re-running a failed deploy with different arguments.
|
|
63
|
+
|
|
64
|
+
`--path` is a suffix appended to a generated base URL, not a full URL.
|
|
65
|
+
|
|
66
|
+
### Inputs: `-i` versus a scenario
|
|
67
|
+
|
|
68
|
+
A scenario is a named input set stored **in the flow definition**, generated
|
|
69
|
+
when someone adds an input to the Start block. Because it travels with the
|
|
70
|
+
flow, `-s "Staging"` is reproducible across invocations and across people,
|
|
71
|
+
where `-i key=value` is per-invocation. Start-block inputs can be declared
|
|
72
|
+
secret, which is what `--show-secrets` unmasks in dry-run output.
|
|
73
|
+
|
|
74
|
+
Precedence: `-s` supplies payload, headers, and query; `--headers` and
|
|
75
|
+
`--query` override it; `-i`/`-f` override its values.
|
|
76
|
+
|
|
77
|
+
### Identifiers
|
|
78
|
+
|
|
79
|
+
`flows list` is the only way to turn a flow name into an id —
|
|
80
|
+
`.postman/resources.yaml` maps collections to cloud ids but has no flows
|
|
81
|
+
section, so there is nothing local to read. Both `list` and `list-runs`
|
|
82
|
+
**require** `-w/--workspace`; take that id from `workspace.id` in
|
|
83
|
+
`.postman/resources.yaml`, which `bootstrap` records.
|
|
84
|
+
|
|
85
|
+
Run IDs have no single documented shape (`session-abc123` and `main/1a123ab1`
|
|
86
|
+
both appear in Postman's own material). Use whatever `trigger` or `list-runs`
|
|
87
|
+
printed, verbatim, and apply the same rule to flow ids.
|
|
88
|
+
|
|
89
|
+
### Plan and permission gating
|
|
90
|
+
|
|
91
|
+
`flows run` is documented as Enterprise-only, and the cloud subcommands need
|
|
92
|
+
`postman login`. `Access denied. Please check your permissions for the
|
|
93
|
+
specified resource.` on *every* workspace is a credential-scope or plan
|
|
94
|
+
signal, not a wrong-workspace signal — and never means the workspace has no
|
|
95
|
+
flows.
|
|
96
|
+
|
|
97
|
+
## Deploying: propose, confirm, then verify
|
|
98
|
+
|
|
99
|
+
Deploy is the one multi-phase workflow here, because it is mutating and
|
|
100
|
+
because its result is only half-useful without the follow-up check.
|
|
101
|
+
|
|
102
|
+
1. **Resolve the id.** `flows list --workspace <id> --filter "Checkout"`. On
|
|
103
|
+
multiple matches, show name + id + last-updated and let the user pick.
|
|
104
|
+
2. **Propose the path.** Derive it from the flow name — "Checkout" →
|
|
105
|
+
`/checkout` — so the user is confirming a concrete value rather than
|
|
106
|
+
answering an open question. Raise `--auth` here if the trigger will be
|
|
107
|
+
reachable by anyone who learns the URL.
|
|
108
|
+
3. **Confirm, then run** `flows deploy <flowId> --path /checkout`.
|
|
109
|
+
4. **Report the Trigger URL and whether the trigger is enabled.** A deploy can
|
|
110
|
+
land with the trigger off, which looks identical to a broken deploy at call
|
|
111
|
+
time. If it is off, offer `flows update <flowId> --trigger on`.
|
|
112
|
+
|
|
113
|
+
When the deploy existed only so the flow could be run, trigger it in the same
|
|
114
|
+
turn and report the Run ID — deploy-then-trigger is one job.
|
|
115
|
+
|
|
116
|
+
## Running and triggering
|
|
117
|
+
|
|
118
|
+
Show the command before running it, and map the request onto flags: inputs to
|
|
119
|
+
`-i`, a payload file to `-f`, query to `-q`, headers to `--headers`, a named
|
|
120
|
+
scenario to `-s`.
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
postman flows run postman/flows/checkout.json -i amount=4200
|
|
124
|
+
postman flows trigger <flowId> -i amount=4200
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
`run` is documented as Enterprise-only, so check the plan before building a
|
|
128
|
+
workflow on the local path. Where the flow is already in Cloud View, `trigger`
|
|
129
|
+
covers the gap; a Local View flow has no such fallback, since it cannot be
|
|
130
|
+
deployed.
|
|
131
|
+
|
|
132
|
+
`-n/--dry-run` on `trigger` prints the resolved URL and payload without
|
|
133
|
+
sending — worth reaching for when a flow writes to real systems, since a
|
|
134
|
+
trigger is not a read-only probe. For CI, `--output json` and `--reporters
|
|
135
|
+
html` persist results, and `--workspace` is required if the flow contains
|
|
136
|
+
connector blocks (it fails at the block, not at startup).
|
|
137
|
+
|
|
138
|
+
Report the Run ID on every trigger, including successes; it is the only handle
|
|
139
|
+
on the run afterwards.
|
|
140
|
+
|
|
141
|
+
Two failures are recoverable rather than terminal, and both recover through a
|
|
142
|
+
confirmed mutation. A 404 hinting `To deploy it, run: postman flows deploy`
|
|
143
|
+
means the flow exists but was never deployed — offer the deploy above, then
|
|
144
|
+
re-trigger. A disabled-trigger error means it is deployed but not accepting
|
|
145
|
+
calls — offer `flows update <flowId> --trigger on`, then trigger.
|
|
146
|
+
|
|
147
|
+
## Debugging a run
|
|
148
|
+
|
|
149
|
+
A trigger's response body is the Response block's output. A flow can answer
|
|
150
|
+
200 with a failed block upstream, and a 500 says nothing about which block
|
|
151
|
+
produced it — so read the run, not the response.
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
postman flows list-runs --workspace <id> --flow <flowId> --range 3d
|
|
155
|
+
postman flows get-run --run-id <runId> --logs
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
`list-runs` recovers a Run ID nobody wrote down; its `--range` defaults to
|
|
159
|
+
`1h`, so widen it before concluding a run is missing. Start `get-run` without
|
|
160
|
+
`--logs` and add them when the summary does not explain the failure;
|
|
161
|
+
`--filter` narrows to a block-id prefix.
|
|
162
|
+
|
|
163
|
+
Report the failing block, the reason, and the run status:
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
Run session-abc123 — failed
|
|
167
|
+
Failing block: "HTTP Request (Get Orders)"
|
|
168
|
+
Reason: downstream returned 504 after 10s timeout
|
|
169
|
+
Status: error
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Critical Rules
|
|
173
|
+
|
|
174
|
+
1. **Resolve ids, never infer them.** A name is not an id, and no id format is
|
|
175
|
+
documented well enough to validate against. Ambiguous name → present
|
|
176
|
+
candidates and ask.
|
|
177
|
+
2. **`deploy` and `update` need explicit confirmation.** They change what the
|
|
178
|
+
flow does for every caller: a deploy exposes a trigger path, `--trigger
|
|
179
|
+
on|off` starts or stops accepting calls, and `--auth off` removes
|
|
180
|
+
authentication from a live trigger.
|
|
181
|
+
3. **Report the failing block, not the log.** `--logs` output is input to your
|
|
182
|
+
analysis; the user needs the block, the reason, and the status.
|
|
183
|
+
4. **Surface CLI errors verbatim** and read them literally. "Flow file not
|
|
184
|
+
found", a required-option error, and "Access denied" have three different
|
|
185
|
+
fixes, and only the last is about permissions.
|
|
186
|
+
5. **A missing or unauthenticated CLI is `bootstrap`'s job** — route there
|
|
187
|
+
rather than improvising an install or a second login.
|
|
188
|
+
|
|
189
|
+
## Anti-patterns
|
|
190
|
+
|
|
191
|
+
1. **Don't substitute `run` for `trigger` when a flow isn't deployed.** A
|
|
192
|
+
green local run says nothing about the deployed path a caller hits, and a
|
|
193
|
+
Local View flow cannot be deployed at all.
|
|
194
|
+
2. **Don't hunt for a different workspace id when access is denied across
|
|
195
|
+
every workspace you try.** A blanket denial points at the credential's
|
|
196
|
+
scope or the plan, not at the id.
|
|
197
|
+
3. **Don't pass `-x/--suppress-exit-code` in CI.** It makes a failed flow
|
|
198
|
+
report success to the pipeline, which removes the only thing gating it.
|
|
199
|
+
4. **Don't put reusable inputs on the command line.** A payload that matters
|
|
200
|
+
more than once belongs in a Start-block scenario, where it travels with the
|
|
201
|
+
flow.
|
|
202
|
+
|
|
203
|
+
## Reference
|
|
204
|
+
|
|
205
|
+
- [Flows CLI flags](reference/flow_cli_flags.md) — full flag tables per
|
|
206
|
+
subcommand, the BETA dataset-iteration flags, and the short-flag collisions
|
|
207
|
+
between subcommands. Read before composing a command with flags not shown
|
|
208
|
+
above.
|
|
209
|
+
- `bootstrap` skill — CLI install, login, and the workspace id these commands
|
|
210
|
+
require.
|
|
211
|
+
- `api-discovery` skill — `postman search flows` finds a flow by text across
|
|
212
|
+
Postman, a different dataset from `flows list`'s workspace enumeration.
|