Level 3 · Senior Automation · Practice 02

API Auth Flows

Log in once, capture the token into an environment variable, and reuse it automatically on every downstream request.

1 Goal

By the end of this exercise you will have a Postman collection called Bootcamp Auth Flow containing three requests: a login call to reqres.in that extracts the returned token and writes it to a collection variable, a follow-up authenticated request to httpbin.org/bearer that sends the token in an Authorization header, and a protected Basic Auth check against httpbin.org/basic-auth/user/passwd. Every request has a test script that asserts the status code and at least one response body field.

Why this matters: almost every real API testing job starts the same way — log in, grab a token, call the thing you actually wanted to test. If you can't do this cleanly in Postman you can't build a regression pack, and you can't run it in Newman from a CI pipeline.

2 Install the tool

Postman has a free desktop app. You do not need a paid account for this exercise — everything here works with a free Postman account (or even without signing in, using a local-only workspace).

  1. Download Postman. Go to postman.com/downloads and pick your platform.

    Click Windows 64-bit. Run the downloaded Postman-win64-Setup.exe. It installs to %LOCALAPPDATA%\Postman\ and launches automatically.

    Download the .zip for your chip (Intel or Apple silicon). Unzip, then drag Postman.app to /Applications/. First launch may need: System Settings → Privacy & Security → Open Anyway.

    On Ubuntu/Debian the snap is the easiest install:

    sudo snap install postman

    Or download the .tar.gz tarball from the website and extract to /opt/Postman.

  2. Skip or complete sign-in. On first launch Postman prompts for a login. Click Skip and go to app at the bottom (free, no account needed) or sign in with a free account if you want cloud sync.
  3. Verify Postman is working. In the top bar, click the + to open a new tab. In the URL field type https://httpbin.org/get and click Send. You should get a 200 OK with a JSON body containing "url": "https://httpbin.org/get". If this fails, your machine cannot reach the public internet — check your proxy or firewall before continuing.

3 Project setup

  1. Create a collection. In the left sidebar click Collections+ Create collection. Name it Bootcamp Auth Flow. Press Enter.
  2. Create an environment. In the left sidebar click Environments+ Create environment. Name it bootcamp-local. Add two variables:
    VariableInitial valueCurrent valueType
    baseUrlhttps://reqres.inhttps://reqres.indefault
    authToken(leave blank)(leave blank)secret

    Click Save. Then activate the environment using the dropdown in the top-right corner of the workspace — select bootcamp-local.

  3. Confirm active environment. The top-right dropdown should read bootcamp-local. If it says No Environment, your variables will not resolve and every request will 404.
Variable scopes in Postman: Global, Environment, Collection, Local. We use an environment variable for the token so it is easy to wipe between runs, and we keep baseUrl in the environment so you can swap in a staging URL later without touching requests.

4 Build the collection

You will add three requests in order. For each one, right-click Bootcamp Auth FlowAdd request, name it, then configure the tabs as shown.

Request 1 — Login

  • Method: POST
  • URL: {{baseUrl}}/api/login
  • Headers tab: Content-Type: application/json, x-api-key: reqres-free-v1
  • Body tab: select raw and JSON, then paste:
    {
      "email": "eve.holt@reqres.in",
      "password": "cityslicka"
    }
  • Tests tab: paste the script below. It asserts a 200, pulls the token out of the response, and writes it into the environment variable we just created.
    pm.test("Login returns 200", function () {
        pm.response.to.have.status(200);
    });
    
    pm.test("Response body contains a token", function () {
        const body = pm.response.json();
        pm.expect(body).to.have.property("token");
        pm.expect(body.token).to.be.a("string").and.not.empty;
    });
    
    pm.test("Token stored in environment", function () {
        const token = pm.response.json().token;
        pm.environment.set("authToken", token);
        pm.expect(pm.environment.get("authToken")).to.eql(token);
        console.log("authToken set to:", token);
    });

Request 2 — Authenticated bearer check

  • Method: GET
  • URL: https://httpbin.org/bearer
  • Authorization tab: Type = Bearer Token. In the Token field enter {{authToken}}. Postman will substitute the environment variable at send time.
  • Tests tab:
    pm.test("Bearer check returns 200", function () {
        pm.response.to.have.status(200);
    });
    
    pm.test("Authenticated flag is true", function () {
        const body = pm.response.json();
        pm.expect(body.authenticated).to.equal(true);
    });
    
    pm.test("Echoed token matches the one we stored", function () {
        const body = pm.response.json();
        pm.expect(body.token).to.equal(pm.environment.get("authToken"));
    });

Request 3 — Basic Auth sanity

This request proves you also understand Basic Auth — a common fallback for legacy services.

  • Method: GET
  • URL: https://httpbin.org/basic-auth/user/passwd
  • Authorization tab: Type = Basic Auth. Username = user, Password = passwd.
  • Tests tab:
    pm.test("Basic auth succeeds with correct credentials", function () {
        pm.response.to.have.status(200);
    });
    
    pm.test("Response identifies the authenticated user", function () {
        const body = pm.response.json();
        pm.expect(body.authenticated).to.equal(true);
        pm.expect(body.user).to.equal("user");
    });

Save every request (Ctrl+S on Windows/Linux, +S on macOS).

Heads-up about reqres.in: since 2025, reqres.in requires a header x-api-key: reqres-free-v1 on every request. If you get a 401 on the login request, double-check this header is present on the Headers tab and spelled exactly as shown.

5 Run & verify

There are two ways to run the collection: one request at a time (click Send on each, in order), or in bulk via the Collection Runner.

  1. Single-request run. Click LoginSend. Scroll to the Test Results tab below the response. All three tests should be green. Repeat for Authenticated bearer check, then Basic Auth sanity. You will see three tests pass on each of the three requests — nine passes total.
  2. Bulk run with the Collection Runner. Right-click Bootcamp Auth FlowRun collection. Leave iterations at 1, delay at 0. Ensure bootcamp-local is the selected environment. Click Run Bootcamp Auth Flow.
  3. Expected result. The Runner shows a green bar across the top: 9/9 tests passed. You will see each request, its status code, and every test assertion. Click any request to expand it.

Expected login response (abbreviated):

POST https://reqres.in/api/login
200 OK

{
    "token": "QpwL5tke4Pnpja7X4"
}

Expected bearer response:

GET https://httpbin.org/bearer
200 OK

{
    "authenticated": true,
    "token": "QpwL5tke4Pnpja7X4"
}
Reading the token in the environment: click the eye icon next to the environment dropdown (top-right). You should see authToken populated with the value you received from the login request. This is what request 2 reads via {{authToken}}.

6 Troubleshooting

Login returns 401 Missing API key

reqres.in now requires the x-api-key: reqres-free-v1 header on every request. Add it on the Headers tab of the Login request. If you are using the Authorization tab instead, that sets Authorization — not x-api-key — so it has no effect here.

Bearer request sends Authorization: Bearer {{authToken}} literally

Postman is not substituting the variable. Three causes:

  1. No active environment. The top-right dropdown says No Environment. Switch it to bootcamp-local.
  2. Variable typo. Check the variable name is authToken everywhere (not authtoken or auth_token). Postman variables are case-sensitive.
  3. Login never ran. Run the Login request first, so the test script writes the token. Variables are not set until the containing request completes.
TypeError: pm.response.json is not a function

The server returned a non-JSON body (usually an HTML error page). Click the Body tab on the response — if you see <html>, the upstream endpoint is down or your request hit a proxy. Fix the request first, then the test script will stop throwing.

Tests appear to pass but no test results show under the response

You put the assertions on the Pre-request Script tab instead of the Tests tab. Move them to Tests — pre-request scripts run before the request is sent and do not have pm.response available.

7 Challenge

Extend the collection

  1. Add a pre-request script to the collection root that checks whether authToken is empty and, if so, automatically calls /api/login using pm.sendRequest() before the current request fires. This is how real teams avoid re-logging in between tests.
  2. Export and run headless with Newman. Export the collection and the environment as JSON. Install Newman globally (npm install -g newman) and run newman run Bootcamp-Auth-Flow.postman_collection.json -e bootcamp-local.postman_environment.json. All nine assertions should pass in the terminal, with no Postman app open.