Postman pre-request scripts are the unsung heroes of API testing, letting you sculpt the exact state your API needs before it even sees a request.

Let’s see them in action. Imagine you’re testing an e-commerce API. Before you can add an item to a cart, you need a valid cartId. You don’t want to hardcode this; it needs to be dynamic.

Here’s a pre-request script that creates a new cart and stores its ID for later use:

// Pre-request Script for creating a cart
const createCartResponse = pm.sendRequest({
    url: 'https://your-api.com/carts',
    method: 'POST',
    header: {
        'Content-Type': 'application/json'
    },
    body: {
        mode: 'raw',
        raw: JSON.stringify({}) // Empty body for cart creation
    }
}, function (err, res) {
    if (err) {
        console.log("Error creating cart: " + err);
        // Optionally, fail the request if cart creation is critical
        // pm.request.stop("Failed to create cart.");
    } else {
        const cartData = res.json();
        pm.environment.set("cartId", cartData.id); // Store cartId in environment
        console.log("Cart created with ID: " + cartData.id);
    }
});

This script, attached to a request that uses cartId (like adding an item to the cart), runs before that request is sent. It makes a POST call to /carts, parses the response, and crucially, stores the id from the response into a Postman environment variable named cartId.

Now, in your main request, you can reference this dynamically generated cartId:

// Request Body for adding an item to cart
{
  "itemId": "12345",
  "quantity": 1,

  "cartId": "{{cartId}}" // Dynamically inserted

}

This is powerful because it automates setup. You’re not manually creating a cart, copying its ID, and pasting it into every subsequent request. Postman handles it.

The core problem pre-request scripts solve is managing transient state. Many APIs are stateful. A user needs to log in before they can access protected resources. An order needs to exist before items can be added to it. A resource must be created before it can be updated or deleted. Manually setting up this state for each test run is tedious and error-prone.

Pre-request scripts allow you to programmatically:

  • Generate dynamic data: Create users, carts, orders, or any other resource needed for a test.
  • Fetch necessary IDs or tokens: Retrieve authentication tokens, session IDs, or resource identifiers from previous requests or external sources.
  • Modify request payloads: Dynamically alter JSON or form-data bodies based on pre-existing conditions or generated data.
  • Set up test environments: Prepare specific data configurations or user states within your Postman environment.
  • Handle complex workflows: Orchestrate multi-step API interactions where the output of one step is the input for the next.

Internally, Postman executes these scripts in a sandboxed JavaScript environment before sending the actual HTTP request associated with the script. You have access to the pm object, which provides methods for interacting with the Postman runtime:

  • pm.request: Access information about the current request.
  • pm.response: Access information about the previous response (if applicable, e.g., in chained requests).
  • pm.environment, pm.collectionVariables, pm.globals: Read and write variables to manage state across requests and collections.
  • pm.sendRequest: Make additional, independent HTTP requests from within your script. This is what we used to create the cart.
  • pm.expect: For assertion-style tests within the script itself (though typically used in "Tests" tab).

You can also use console.log() to output debugging information that appears in the Postman Console (View > Show Postman Console).

The pm.sendRequest method is particularly interesting because it allows you to make additional requests from within a pre-request script. This is not about the request the script is attached to; it’s a separate, asynchronous call. The callback function receives an error object (err) and a response object (res). This is how you can create dependent resources, fetch authentication tokens, or perform any other setup that requires an API call before your main request executes.

Crucially, pm.sendRequest is asynchronous. If you need the result of pm.sendRequest to directly influence the current request’s payload or parameters, you must ensure the script waits for the pm.sendRequest to complete. The callback pattern shown above is the standard way to handle this. If you don’t handle the asynchronous nature correctly and try to use the variable before it’s set, your main request will likely fail with an invalid or missing value.

When you’re debugging these scripts, remember that any console.log statements will appear in the Postman Console. This is invaluable for tracing variable values, checking response bodies from pm.sendRequest, and understanding the flow of execution.

The next logical step after mastering dynamic state setup is handling complex authentication flows, such as OAuth 2.0, where obtaining a token often involves multiple requests and specific parameter handling.

Want structured learning?

Take the full Postman course →