Structuring Collections for Long-Term Maintainability
A Postman collection that grows past a few dozen requests without structure becomes unusable fast. Group requests into folders by resource or microservice (Users, Orders, Payments) rather than by HTTP verb, and use consistent naming like "GET /orders/{id} - fetch single order" so the request name alone tells you what it does without opening it.
Cricket analogy: Just as a team sheet groups players by role - openers, middle order, bowlers, wicketkeeper - rather than listing all eleven names randomly, a collection folder groups requests by resource so a new teammate can find the Payments endpoints as fast as a captain finds his death-over specialists.
Environments and Variable Scoping
Postman resolves variables in a strict precedence order: local, then data, then environment, then collection, then global. Always reference hosts and IDs as {{baseUrl}} or {{orderId}} instead of hardcoding literal strings, and mark tokens or API keys as "secret" type so they're masked in the UI and excluded from sync exports - this is what lets the same collection run unmodified against dev, staging, and prod by simply switching the active environment.
Cricket analogy: A DRS review checks evidence in a fixed order - ball tracking, then snickometer, then hot spot - and Postman's variable resolution works the same way, checking local scope before falling back to collection or global, so the same request behaves predictably across every environment just like the review process is consistent across every match.
Pre-request Scripts and Dynamic Variables
Pre-request scripts run before the request is sent, making them the right place to generate a timestamp, compute an HMAC signature, or fetch and cache an OAuth token so it doesn't need to be requested on every single call. Use pm.variables.set() for values scoped only to that run, and pm.collectionVariables.set() when a value like a freshly issued token needs to persist and be reused by later requests in the same collection run.
Cricket analogy: A bowler's pre-delivery routine - checking the field, adjusting the run-up mark - happens before every ball is bowled, just as a pre-request script runs and prepares a fresh timestamp or token before every API call is actually sent.
// Pre-request Script: fetch and cache an OAuth token if it's missing or expired
const tokenExpiry = pm.collectionVariables.get("tokenExpiry");
const now = Date.now();
if (!tokenExpiry || now > parseInt(tokenExpiry, 10)) {
const authRequest = {
url: pm.environment.get("authUrl"),
method: "POST",
header: { "Content-Type": "application/json" },
body: {
mode: "raw",
raw: JSON.stringify({
client_id: pm.environment.get("clientId"),
client_secret: pm.environment.get("clientSecret"),
grant_type: "client_credentials"
})
}
};
pm.sendRequest(authRequest, (err, res) => {
if (!err) {
const json = res.json();
pm.collectionVariables.set("accessToken", json.access_token);
pm.collectionVariables.set("tokenExpiry", now + json.expires_in * 1000);
}
});
}
// Test Script: assert the response and status code
pm.test("Status code is 200", () => {
pm.response.to.have.status(200);
});
pm.test("Response has an order id", () => {
const body = pm.response.json();
pm.expect(body).to.have.property("orderId");
});For long-lived secrets like client credentials, store them in Postman Vault instead of a plain environment variable - vault values (referenced as {{vault:secretName}}) are encrypted locally and never leave your machine, even when the collection is synced to the cloud.
Writing Effective Tests and Assertions
Every request should carry at least a status-code assertion and a shape assertion written inside a pm.test() block using the Chai-based assertion library exposed as pm.expect. For anything beyond a handful of fields, validate the full response shape with pm.response.to.have.jsonSchema(schema) instead of asserting individual properties one by one, since a schema catches missing or mistyped fields that ad-hoc assertions would silently miss.
Cricket analogy: Third umpires don't just glance at a replay once - they check multiple angles and ball-tracking data before confirming a decision, the same layered scrutiny a pm.test block applies by checking status code, response shape, and field values before calling a request "passed."
Never hardcode bearer tokens, API keys, or passwords directly into a test or pre-request script and commit the collection to git - even with "secret" variable types, raw values pasted into script bodies are stored in plain text in the collection JSON. Use environment or vault variables and add exported collection files with embedded secrets to .gitignore.
- Group requests into folders by resource or microservice, not by HTTP verb, and use descriptive request names.
- Reference hosts and IDs with variables like {{baseUrl}} instead of hardcoding literal strings.
- Understand Postman's variable precedence: local, then data, then environment, then collection, then global.
- Use pre-request scripts to generate timestamps, signatures, or cached OAuth tokens before a request fires.
- Store long-lived secrets in Postman Vault rather than plain environment variables.
- Validate full response shapes with pm.response.to.have.jsonSchema() rather than asserting fields one by one.
- Never commit collections containing hardcoded tokens or secrets to version control.
Practice what you learned
1. In what order does Postman resolve a variable referenced in a request?
2. Where should a pre-request script store an OAuth token so later requests in the same collection run can reuse it?
3. What is the main advantage of pm.response.to.have.jsonSchema() over asserting individual fields?
4. Why should secrets be stored in Postman Vault or environment variables rather than hardcoded in a script?
5. What is the recommended way to group requests in a large collection?
Was this page helpful?
You May Also Like
Postman Quick Reference
A condensed cheat sheet of Postman variable scopes, common pm.* scripting snippets, and Newman CLI commands for everyday use.
Postman Interview Questions
Commonly asked Postman interview questions covering variable scoping, scripting, authentication, and CI/CD integration, with concise model answers.
Designing APIs with Postman (OpenAPI Import)
Using Postman's API Builder to design an API from an OpenAPI specification, generate mock servers, and keep implementation in sync with the contract.
Postman vs Insomnia vs curl
Comparing Postman, Insomnia, and curl across usability, collaboration, scripting, and automation to decide which fits a given API workflow.