Here's a real scenario. You need to test the "Get User Profile" endpoint. But it requires an auth token. To get the token, you need to call the "Login" endpoint first. The login response gives you a token. You store it. The next request uses it. That's chaining.
Chained requests are the backbone of real API testing. Almost nothing works in isolation. Login gives you a token. Create Order gives you an order ID. Get Order needs that ID. Cancel Order needs it too. It's a chain.
// POST /login — Post-response script
// Response body: { "token": "eyJhbGciOiJIUzI1NiJ9...", "userId": 42 }
const response = pm.response.json();
pm.test("Login successful", function () {
pm.response.to.have.status(200);
});
pm.test("Token is returned", function () {
pm.expect(response.token).to.be.a("string");
pm.expect(response.token).to.not.be.empty;
});
// Store the token for the next request
pm.environment.set("authToken", response.token);
pm.environment.set("userId", response.userId);
console.log("Token saved:", response.token.substring(0, 20) + "...");In your GET /profile request, set the Authorization header to: Bearer {{authToken}}. Postman will replace {{authToken}} with the value you stored in Step 1.
// GET /profile — Post-response script
// The request header has: Authorization: Bearer {{authToken}}
const profile = pm.response.json();
pm.test("Profile retrieved successfully", function () {
pm.response.to.have.status(200);
});
pm.test("Profile belongs to logged-in user", function () {
const expectedUserId = pm.environment.get("userId");
pm.expect(profile.id).to.eql(parseInt(expectedUserId));
});
pm.test("Profile has required fields", function () {
pm.expect(profile).to.have.property("name");
pm.expect(profile).to.have.property("email");
pm.expect(profile).to.have.property("id");
});Request 1 — POST /posts: Create a post. In Post-response script, extract the new post ID and save it: pm.environment.set("postId", response.id)
Request 2 — GET /posts/{{postId}}: Fetch the created post. Assert the title matches what you sent.
Request 3 — PUT /posts/{{postId}}: Update the post title. Assert status 200 and new title in response.
Request 4 — DELETE /posts/{{postId}}: Delete the post. Assert status 200 or 204.
Run the collection in order. Each request depends on the previous one's output.
// Request 1: POST /posts — Post-response script
const newPost = pm.response.json();
pm.test("Post created successfully", function () {
pm.response.to.have.status(201);
});
pm.test("Post has an ID", function () {
pm.expect(newPost.id).to.be.a("number");
});
// Save for next requests
pm.environment.set("postId", newPost.id);
pm.environment.set("postTitle", newPost.title);
console.log("Created post ID:", newPost.id);// Request 2: GET /posts/{{postId}} — Post-response script
const post = pm.response.json();
const expectedTitle = pm.environment.get("postTitle");
pm.test("Retrieved the correct post", function () {
pm.response.to.have.status(200);
pm.expect(post.id).to.eql(parseInt(pm.environment.get("postId")));
});
pm.test("Title matches created post", function () {
pm.expect(post.title).to.eql(expectedTitle);
});Chained requests MUST run in order. If you run Request 2 before Request 1, the {{postId}} variable won't exist and the request will fail. Always use Collection Runner with the requests in the correct sequence.
Q: How do you handle dependent API requests in Postman? For example, login then access a protected endpoint.
A: I chain requests using environment variables. In the login request's Post-response script, I extract the auth token using pm.response.json().token and store it with pm.environment.set("authToken", token). In the next request, I set the Authorization header to "Bearer {{authToken}}." When I run the collection, requests execute in order — login runs first, stores the token, and all subsequent requests use it automatically. I also add assertions to the login response to ensure the token is valid before proceeding.
Key Point: Chain requests by extracting values from one response and storing them as variables for the next request. Use pm.environment.set() to pass data between requests.