skip to content

In a saved Postman collection, which values can an event's `listen` field take, and when does each script run?

level: middleimportance: must knowfreq 62%

answer

  1. Two names, never three
  2. One before the send, one after
  3. The reply exists in only one hook
  4. prerequest and test

basics

~10 s

Exactly two: prerequest, which runs just before the request is handed to the transport, and test, which runs after the reply arrives. No third, post-send listener name exists in the format.

solid answer

~40 s

In the collection format a script never floats free — it hangs from an `event` entry whose `listen` field names the moment it runs, and only `prerequest` and `test` are real values. A `prerequest` listener fires immediately before the send; a `test` listener fires once the reply is back. They are not interchangeable, because the sandbox surface differs by moment: `pm.response` is present only in the `test` hook, and `pm.execution.skipRequest` only in `prerequest`. Only the earlier hook can still change what goes out — the runtime reads back edits to `url`, `method`, `headers`, `body` and `auth`. A post-send listener name that shows up in documentation comments is not API: the runtime dispatches those two moments and nothing else, so any other value matches no dispatch and the code simply never runs.

code

json · 18 lines
json
{
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "type": "text/javascript",
        "exec": ["pm.request.headers.add({ key: 'X-Trace', value: 'abc-123' });"]
      }
    },
    {
      "listen": "test",
      "script": {
        "type": "text/javascript",
        "exec": ["const status = pm.response.code;"]
      }
    }
  ]
}

go deeper

for a junior

Recall that a script is attached to a moment, and that there are two: one before the request goes out and one after the reply comes back. Be able to say which one sees the response.

for a middle

Explain the mechanics: the collection file's event entry carries a listen value of prerequest or test, and the sandbox surface differs by moment — pm.response in one, pm.execution.skipRequest in the other.

for a senior

Demonstrate the diagnostic reflex. When a script 'runs but does nothing', check the moment before the code, because a wrongly-placed script fails silently rather than throwing, and show how you confirm it from inside the script.

for a principal

Own the convention. Decide as a team where signing, correlation and shaping work lives versus checking work, so scripts are placed by rule rather than by habit, and mistyped or misplaced listeners are caught in review rather than in a failing run.

## Where a script hangs, and when it runs A **Postman collection** is a JSON document, and a script never floats loose inside it. It hangs from an entry in an `event` array — a construct the **collection format** declares, not something the app invents at runtime. Each entry carries two things that matter here: a `listen` field naming **when** the code runs, and a `script` object holding the code. The `listen` value is the entire subject of this question, because it decides which of the two moments around a single send the code occupies. The format admits **exactly two** listener names: - **`prerequest`** — the code runs immediately **before** the request is handed to the transport. Nothing has been sent; nothing has replied. - **`test`** — the code runs **after** the reply has come back. The send is finished and cannot be taken back. That is the whole vocabulary. Everything else about scripting in this tool — assertions, chaining values forward, redirecting a run — is code written *inside* one of those two moments, not a third moment. ## What each moment can see The two hooks are not the same room with a different clock. The `pm.*` surface the **sandbox** exposes is genuinely different in each, and that difference is the practical reason to care which one you picked. | | `prerequest` | `test` | |---|---|---| | when it runs | before the send | after the reply | | `pm.response` | absent — nothing has replied yet | present | | `pm.execution.skipRequest` | present — the send can still be abandoned | absent | | edits that reach the wire | `url`, `method`, `headers`, `body`, `auth` | none — the send already happened | Read that table as a rule rather than a list of quirks: **the moment decides the surface, and the surface decides what your code can possibly do.** A script that needs the reply must live in `test`. A script that needs to shape the outgoing call, or to decide it should not happen at all, must live in `prerequest`. ## Why the wrong moment fails quietly The painful property of this pair is that choosing wrongly rarely looks like an error. Code placed in the later hook that edits the request runs perfectly well: the objects exist, the assignments succeed, nothing throws. The request it edited has simply already gone. Symmetrically, code in the earlier hook that reaches for the reply finds nothing there, because there is no reply to find. Both are silent, and both present as "my script does not work" rather than as a stack trace. So the diagnostic habit worth building is: **before debugging the code, confirm the moment.** Two cheap checks: 1. Read the `listen` value on the `event` entry the script hangs from — it says the answer outright. 2. From inside the running script, probe the surface: if `pm.response` resolves, you are after the send, and nothing you write onto the request can still travel. ## The third name that is not real Documentation comments in this ecosystem mention a post-send listener name that reads like a natural third option next to `prerequest`. It is a comment, not an interface. The format does not accept it and the runtime does not dispatch it, so an `event` entry declaring it matches nothing and its code never executes — again with no error to notice. **A name appearing in a doc comment is not evidence that it is API.** The two real values are `prerequest` and `test`, and "the post-send hook" is prose for `test`, not a separate identifier. ## Splitting work across the send Because the two moments are separate dispatches, one script cannot straddle the send. Work that spans it becomes **two** `event` entries on the same item: - the `prerequest` entry builds whatever the call needs — a computed header, a rewritten URL, a body shaped from data; - the `test` entry looks at what came back. Anything the first needs to hand to the second travels through a variable scope rather than through a shared local, because the two executions do not share a scope. ## What `listen` does not decide Two things are worth ruling out explicitly, because they are commonly folded into this question and are separate concerns: - **Where** the entry hangs — on the collection, on a folder, or on the request itself — is a placement question, not a `listen` question. The listener name says *when* relative to the send; placement says *whose* scripts participate. - **What the code says** — an assertion, a variable write, a computed signature — is orthogonal. The same statement is legal in both hooks; only its effect changes. Hold those apart and the field becomes simple: `listen` is a two-valued switch that picks a side of the send, and everything else follows from which side you picked.

  • If a script must build a signature and then check the reply, how many event entries does that take?
    Two — a `prerequest` entry for the signing work and a `test` entry for the check. One script cannot straddle the send: the two moments are separate dispatches with different sandbox surfaces, so only the later one sees `pm.response` and only the earlier one can still change what goes out. Values pass between them through a variable scope, not a shared local.
  • What happens to an event entry whose `listen` value is neither of the two names?
    Nothing runs. The runtime dispatches the pre-send and post-reply moments only, so an entry listening for any other name matches no dispatch and its code never executes. There is no error and no warning, which is why a mistyped listener presents as a script that quietly stopped working rather than as a failure.

saying these in an interview costs you the question

  • Believes a third, post-send listener name exists
  • Puts outgoing-request edits in the after-the-reply hook
  • Expects the reply object inside a pre-request script
  • Treats the two hooks as interchangeable homes for any code
  • Thinks one script can span both sides of the send