skip to content

In a Postman collection, how does a test script hand an id from one response to the next request?

level: juniorimportance: must knowfreq 76%

answer

  1. Two steps: read it, then store it
  2. Parse the reply in the test script
  3. Write into a store the run keeps
  4. pm.environment.set or pm.collectionVariables.set
  5. The next request asks for the same name

basics

~10 s

Read the value out of the reply in a test script, then write it into a tracked store with pm.environment.set, pm.collectionVariables.set or pm.globals.set. The next request refers to that same name.

solid answer

~40 s

Two explicit steps, both in the test script of the first request. Parse the reply with `pm.response.json()` and pull out the field you need. Then store it under a name with `pm.environment.set('orderId', id)`, `pm.collectionVariables.set('orderId', id)` or `pm.globals.set('orderId', id)` — those three scopes are the ones the runtime carries back out of the sandbox when the script finishes. The following request then refers to `{{orderId}}` wherever it needs the value: in the URL, a header or the body. What does not work is `pm.variables.set`, which writes a layer local to that one execution, so the next request finds nothing. Pick one store as the collection's handoff and stay with it.

code

javascript · 5 lines
javascript
const order = pm.response.json();

if (order.id) {
    pm.collectionVariables.set('orderId', order.id);
}

go deeper

for a junior

Be ready to write the two lines from memory: parse the reply, then store the field with pm.environment.set or pm.collectionVariables.set. Know that the next request refers to the same name.

for a middle

Explain why the store matters - only globals, environment and collection variables come back out of the sandbox after a script, so the choice of call is what makes the chain work.

for a senior

Show the hygiene around the chain: assert the field before storing it, and unset the name when the flow ends so a leftover from an earlier pass cannot disguise a chain that is broken.

for a principal

Own the convention across a shared collection: one agreed store for handoffs, agreed naming, and agreed cleanup, so nobody has to read every script to know where a value came from.

## The handoff is two deliberate steps Nothing in a collection run moves a value between requests on its own. A request does not inherit the previous reply, and a variable does not update itself because a response happened to contain a field with the same name. Chaining is something a **script** does, in two steps that are easy to state and easy to get half right: 1. **Read** the value out of the response, in the test script of the request that produced it. 2. **Write** it into a store the runtime carries back out of the sandbox, so the next request can find it. Miss the first and you store `undefined`. Miss the second and the value evaporates when the script ends. ## Reading the value out `pm.response.json()` parses the reply body and gives you an ordinary JavaScript value, so the field you want is normal property access — `pm.response.json().id`, or `pm.response.json().data.id` for a wrapped payload. Two habits are worth forming immediately. Read the parsed body into a `const` once rather than calling the parse repeatedly, and check the field is actually there before you store it, because storing `undefined` succeeds silently and moves the failure one request downstream where it is much harder to read. ## Writing it where the run will keep it The sandbox exposes three stores whose script writes the runtime collects and applies to the run: - `pm.globals.set(name, value)` — the widest store; everything the run touches can see it. - `pm.environment.set(name, value)` — tied to the environment selected for this run. - `pm.collectionVariables.set(name, value)` — belongs to the collection itself, so no environment needs to be selected for the chain to work. | Call | Where the value lives | Typical reason to pick it | |---|---|---| | `pm.collectionVariables.set` | with the collection | the chain is internal to this collection and should work anywhere it is run | | `pm.environment.set` | with the selected environment | the value is specific to the target the run is pointed at | | `pm.globals.set` | outside both | you deliberately want the widest reach, accepting the widest blast radius | All three survive to the next request, which is the only property that matters for the chain to work at all. The choice between them is about reach: how much of the run, and how many other collections, can see the name you just wrote. ## The call that does not work `pm.variables.set` is the classic wrong answer, and it is wrong in a way that flatters you. It runs without error, and reading the name back inside the same script returns exactly what you wrote — so every check made from inside the writing script says the handoff succeeded. It writes an execution-local layer that the runtime does not collect, so the value is discarded when the script ends and the next request sees nothing at all. ## Then the dependent request refers to the name Once the value is in a tracked store, the next request uses the ordinary `{{orderId}}` token form wherever the value belongs — in the path, a query parameter, a header, or the body. The important part is that both sides agree on the **name**: the script writes `orderId` and the request asks for `orderId`. A typo on either side is indistinguishable, from the outside, from a chain that never wrote anything. ## Cleaning up after the flow The last habit is the one people skip. A chained value stays in the store after the flow that needed it is done. On the next pass, a request that should have failed loudly because nothing wrote the value instead quietly reuses the previous pass's leftover, and the collection appears healthy while the chain is actually broken. Removing the name at the end of the flow — `pm.environment.unset('orderId')` or `pm.collectionVariables.unset('orderId')` — costs one line and makes every subsequent run tell you the truth about itself. Put together, the whole discipline is: read it, prove it exists, store it in a scope the run keeps, name it identically on both sides, and remove it when you are done with it.

  • Which of the three stores should a collection's handoff go into?
    Whichever the collection has agreed on. `pm.collectionVariables.set` keeps the handoff with the collection itself, so the chain works without any environment selected. `pm.environment.set` ties the value to the target the run is pointed at. `pm.globals.set` gives the widest reach and the widest blast radius. All three survive to the next request; the choice is about reach, not about whether it works.
  • How do you stop a chained value leaking into the next run?
    Remove it when the flow ends, with `pm.environment.unset('orderId')` or `pm.collectionVariables.unset('orderId')`. Otherwise a later pass can read a leftover from an earlier one, and a chain that never wrote anything still looks healthy. The alternative discipline is that every dependent request sets the value itself before use rather than trusting whatever is in the store.

saying these in an interview costs you the question

  • Uses pm.variables.set for the handoff and expects it to survive
  • Assumes the next request picks up the previous reply automatically
  • Stores the field without checking the reply contained it
  • Writes one name in the script and asks for another in the request
  • Never removes the chained name, so stale values hide broken chains