Skip to content

Postman Scripts: Advanced Pre-request and Test Scripting Techniques

DodaTech Updated 2026-06-28 6 min read

In this tutorial, you will learn about Postman Scripts: Advanced Pre. We cover key concepts, practical examples, and best practices to help you master this topic.

Postman scripting extends beyond basic assertions with request chaining, cryptographic functions, date manipulation, XML parsing, external library usage, and reusable snippet libraries for complex test scenarios.

What You'll Learn

Advanced Postman scripting techniques: chaining requests with pm.sendRequest, using CryptoJS for signatures, moment.js for date manipulation, XML2JS for XML APIs, building reusable snippet libraries, and debugging complex scripts.

Why It Matters

Complex API testing scenarios require cryptographic signing, OAuth flows, multi-step request chains, and data transformation. Postman's sandboxed JavaScript runtime supports these natively. DodaTech uses advanced scripts for HMAC-signed Webhook testing and OAuth token refresh chains.

Real-World Use

A DodaTech webhook test needs an HMAC-SHA256 signature in the header. The pre-request script generates the signature using CryptoJS, adds it to headers, and the test script validates the 200 response and signature verification.

flowchart LR
    A["Pre-request\nScript"] --> B["Generate\nHMAC Signature"]
    B --> C["Add Signature\nHeader"]
    C --> D["Send\nRequest"]
    D --> E["Test Script\nRuns"]
    E --> F["Verify Status\nand Signature"]
    style A fill:#dbeafe,stroke:#2563eb
    style B fill:#fef3c7,stroke:#d97706
    style F fill:#bbf7d0,stroke:#16a34a

Chaining Requests

// pm.sendRequest - send additional requests from scripts

// Test: Create user, then verify it exists
pm.test("Create and verify user", function () {
    const newUser = {
        email: `user-${Date.now()}@test.com`,
        name: "Test User",
        password: "SecurePass123!"
    };

    const createRequest = {
        url: pm.collectionVariables.get("base_url") + "/users",
        method: "POST",
        header: {
            "Content-Type": "application/json",
            "Authorization": `Bearer ${pm.environment.get("auth_token")}`
        },
        body: {
            mode: "raw",
            raw: JSON.stringify(newUser)
        }
    };

    pm.sendRequest(createRequest, function (err, response) {
        if (err) {
            console.error("Create failed:", err);
            return;
        }
        pm.expect(response.code).to.equal(201);
        const userId = response.json().id;

        // Now verify the user exists
        const getRequest = {
            url: `${pm.collectionVariables.get("base_url")}/users/${userId}`,
            method: "GET",
            header: {
                "Authorization": `Bearer ${pm.environment.get("auth_token")}`
            }
        };

        pm.sendRequest(getRequest, function (err2, response2) {
            pm.expect(response2.code).to.equal(200);
            pm.expect(response2.json().email).to.equal(newUser.email);
            console.log(`User ${userId} created and verified`);
        });
    });
});

HMAC Signing and CryptoJS

// Pre-request: Generate HMAC-SHA256 signature for webhook testing

const timestamp = Math.floor(Date.now() / 1000).toString();
const payload = pm.request.body.raw || "";
const secret = pm.environment.get("webhook_secret");

// Generate signature using CryptoJS (built-in)
const signature = CryptoJS.HmacSHA256(
    timestamp + "." + payload,
    secret
).toString(CryptoJS.enc.Hex);

// Add signature headers
pm.request.headers.add({
    key: "X-Webhook-Signature",
    value: signature
});
pm.request.headers.add({
    key: "X-Webhook-Timestamp",
    value: timestamp
});

console.log(`Signature: ${signature.slice(0, 20)}...`);
console.log(`Timestamp: ${timestamp}`);

Date Manipulation with Moment.js

// Moment.js is built into Postman sandbox

// Pre-request: Generate date ranges for query params
const now = moment();
const startDate = now.format("YYYY-MM-DD");
const endDate = now.add(30, "days").format("YYYY-MM-DD");

pm.variables.set("start_date", startDate);
pm.variables.set("end_date", endDate);

// Generate timestamps for rate-limiting tests
const oneHourAgo = moment().subtract(1, "hour").unix();
const oneHourLater = moment().add(1, "hour").unix();

console.log(`Query range: ${startDate} to ${endDate}`);

// Test script: validate date format in response
pm.test("Response date is valid ISO format", function () {
    const jsonData = pm.response.json();
    if (jsonData.created_at) {
        const valid = moment(jsonData.created_at, moment.ISO_8601, true).isValid();
        pm.expect(valid).to.be.true;
    }
});

XML Parsing

// xml2js is built into Postman for XML API testing

// Test: Parse XML response and validate
pm.test("XML response has correct structure", function () {
    const xmlData = pm.response.text();
    const parser = new xml2js.Parser({ explicitArray: false });

    parser.parseString(xmlData, function (err, result) {
        if (err) {
            console.error("XML parse error:", err);
            pm.expect.fail("Invalid XML response");
            return;
        }

        // Navigate parsed XML object
        const root = result.response || result.root;
        pm.expect(root).to.have.property("status");
        pm.expect(root.status).to.equal("success");

        if (root.data) {
            const items = Array.isArray(root.data.item)
                ? root.data.item
                : [root.data.item];
            pm.expect(items.length).to.be.at.least(1);
            pm.expect(items[0]).to.have.property("id");
            console.log(`XML parsed: ${items.length} items found`);
        }
    });
});

Reusable Snippet Library

// Pre-request scripts can include reused logic via functions

// Define reusable functions in collection-level pre-request
const TestUtils = {
    // Generate unique test email
    uniqueEmail: function (prefix) {
        return `${prefix || "test"}-${Date.now()}@example.com`;
    },

    // Create auth header
    authHeader: function () {
        return `Bearer ${pm.environment.get("auth_token")}`;
    },

    // Wait for async processing
    waitForStatus: function (checkUrl, targetStatus, maxRetries, callback) {
        let attempts = 0;
        const check = function () {
            attempts++;
            pm.sendRequest({
                url: checkUrl,
                method: "GET",
                header: { "Authorization": TestUtils.authHeader() }
            }, function (err, response) {
                if (err) {
                    callback(err);
                    return;
                }
                const status = response.json().status;
                if (status === targetStatus || attempts >= maxRetries) {
                    callback(null, response);
                } else {
                    setTimeout(check, 1000);
                }
            });
        };
        check();
    }
};

// Usage in individual test:
const email = TestUtils.uniqueEmail("user");
pm.variables.set("user_email", email);
console.log(`Generated email: ${email}`);

Common Mistakes

1. Not Handling pm.sendRequest Callbacks

pm.sendRequest is asynchronous. If you don't put assertions inside the callback, they run before the response arrives. Always nest assertions within the callback function.

2. Overlooking the Sandbox Limitations

Postman sandbox does not support Node.js built-in modules (fs, path, http), browser APIs (fetch, DOM), or npm packages. Use built-in libraries (CryptoJS, moment, xml2js) instead.

3. Infinite Loops with Retries

When polling for async status, always set a max retry limit and timeout. Without limits, a stuck Process runs indefinitely and the collection runner never completes.

4. Not Cleaning Up Test Data

Test scripts that create resources should also delete them. Use pm.sendRequest in the test script to clean up after yourself, especially in CI runs where state persists.

5. Sharing State Across Async Calls

Variables set inside a pm.sendRequest callback may not be available to the next test if the collection runner continues before the callback fires. Use synchronous patterns or the Postman Runner's iteration flow.

Practice Questions

  1. How do you send additional HTTP requests from within a test script?
  2. What built-in cryptographic libraries does Postman provide?
  3. How do you parse XML responses in Postman?
  4. What are the limitations of the Postman script sandbox?

Answers:

  1. Use pm.sendRequest(requestObject, callbackFunction). The callback receives (error, response) when the request completes. All assertions must be inside the callback.
  2. CryptoJS is built-in for HMAC, SHA, MD5, AES, and other crypto operations. Also available: CryptoJS.enc.Hex, CryptoJS.enc.Base64, and CryptoJS.enc.Utf8.
  3. Use the built-in xml2js library. Create a parser with new xml2js.Parser(), call parser.parseString(xmlText, callback), and navigate the resulting JavaScript object.
  4. No filesystem access (fs), no raw networking (net/http), no DOM APIs, no npm module installation (only built-in libraries). Use environment variables instead of file storage.

Challenge: Build a complex test flow: create an order via API, generate HMAC signature for webhook simulation, poll for async status changes with retry logic, validate XML response from a legacy endpoint, clean up created resources, and log all steps to the Postman Console.

FAQ

Can I use npm packages in Postman?

No, Postman sandbox does not support npm. Only built-in libraries (CryptoJS, moment, xml2js, cheerio, lodash, backbone, tv4) are available.

How do I make multiple requests in parallel?

Use pm.sendRequest for each request. Callbacks are async and run in parallel. Use a counter to track completion and run assertions when all requests finish.

Can I debug async scripts?

Yes, the Postman Console shows all log output including from async callbacks. Use console.log with descriptive messages and timestamps to trace async flow.

What is the best way to reuse script logic?

Define utility objects/functions in the collection-level pre-request script. All requests in the collection can access these functions. Export/import via Postman Library if needed across collections.

How do I handle rate limiting in scripts?

Use pm.environment.set('retry_after', response.headers.get('Retry-After')) in the test script. In the pre-request script, check the retry-after value and use pm.waitFor(retry_after) or loop until cleared.

Mini Project

Build an advanced Postman script collection: create a test suite with HMAC-signed webhook verification, async polling with retry logic, XML response parsing, date-range query parameters, chained create-verify-delete flow, rate limit handling, and a reusable utility library. Run with Newman in CI.

What's Next

Newman CLI — run Postman collections from the command line and CI.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro