Episode 3 — NodeJS MongoDB Backend Architecture / 3.9 — REST API Development

3.9.c — Postman for API Testing

In one sentence: Postman is the industry-standard GUI tool for building, testing, and documenting APIs — its collections, environment variables, and test scripts turn manual API exploration into repeatable, automated workflows.

Navigation: <- 3.9.b — API Versioning | 3.9.d — Status Codes in Practice ->


1. What is Postman?

Postman is an API development platform that lets you:

  • Build requests (GET, POST, PUT, PATCH, DELETE) with a visual interface
  • Test responses with built-in scripting
  • Organize requests into collections and folders
  • Automate testing with the collection runner
  • Share collections with your team
  • Document your API automatically from collections
FeatureFree TierPaid Tier
Request builderUnlimitedUnlimited
CollectionsUp to 25 per workspaceUnlimited
Environments5 per workspaceUnlimited
Collection runs25/monthUnlimited
Mock servers1,000 calls/monthHigher limits
Team collaboration3 membersUnlimited

Install: postman.com/downloads (desktop app recommended over web version).


2. Interface Tour

+------------------------------------------------------------------+
|  [Collections]  [APIs]  [Environments]  [Mock Servers]           |
|  (Sidebar)                                                        |
+------------------------------------------------------------------+
|  [GET  v]  http://localhost:3000/api/v1/users  [  Send  ]        |
|                                                                    |
|  [Params]  [Authorization]  [Headers]  [Body]  [Pre-req]  [Tests]|
|                                                                    |
|  Body:                                                             |
|  ( ) none  ( ) form-data  ( ) x-www-form-urlencoded              |
|  (*) raw [JSON v]    ( ) binary    ( ) GraphQL                    |
|  +--------------------------------------------------------------+ |
|  | {                                                             | |
|  |   "name": "Alice",                                           | |
|  |   "email": "alice@example.com"                               | |
|  | }                                                             | |
|  +--------------------------------------------------------------+ |
|                                                                    |
|  Response:  Status: 201 Created  Time: 45ms  Size: 234 B         |
|  [Body]  [Cookies]  [Headers]  [Test Results]                     |
|  +--------------------------------------------------------------+ |
|  | {                                                             | |
|  |   "data": {                                                   | |
|  |     "id": "64a...",                                           | |
|  |     "name": "Alice",                                         | |
|  |     "email": "alice@example.com"                             | |
|  |   }                                                           | |
|  | }                                                             | |
|  +--------------------------------------------------------------+ |
+------------------------------------------------------------------+

Key areas:

  • Method dropdown — GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD
  • URL bar — type or paste your endpoint URL
  • Request tabs — Params, Auth, Headers, Body, Pre-request Script, Tests
  • Response panel — Body (Pretty/Raw/Preview), Headers, Cookies, Test Results

3. Sending Different Request Types

GET — Fetching data

Method: GET
URL:    http://localhost:3000/api/v1/users
Body:   none (GET requests should not have a body)

POST — Creating data

Method: POST
URL:    http://localhost:3000/api/v1/users
Body:   raw / JSON
{
  "name": "Alice",
  "email": "alice@example.com",
  "password": "securePass123"
}

PUT — Full replacement

Method: PUT
URL:    http://localhost:3000/api/v1/users/64abc123
Body:   raw / JSON
{
  "name": "Alice Updated",
  "email": "newalice@example.com",
  "password": "newSecurePass456"
}

PATCH — Partial update

Method: PATCH
URL:    http://localhost:3000/api/v1/users/64abc123
Body:   raw / JSON
{
  "name": "Alice Patched"
}

DELETE — Removing data

Method: DELETE
URL:    http://localhost:3000/api/v1/users/64abc123
Body:   none (typically)

4. Headers and Body Types

Adding custom headers

Key                    Value
---                    -----
Content-Type           application/json       (auto-set when you pick raw/JSON)
Authorization          Bearer eyJhbGciOiJ...
X-Request-ID           550e8400-e29b-41d4-a716
Accept                 application/json

Body formats

FormatWhen to useContent-Type
raw / JSONMost API requestsapplication/json
form-dataFile uploads, multipart formsmultipart/form-data
x-www-form-urlencodedSimple form submissionsapplication/x-www-form-urlencoded
binarySending raw file bytesDepends on file type
GraphQLGraphQL queriesapplication/json

File upload with form-data

Method: POST
URL:    http://localhost:3000/api/v1/upload
Body:   form-data

Key        Type      Value
---        ----      -----
avatar     File      [Select file: photo.jpg]
username   Text      alice

5. URL Parameters and Query Parameters

Path parameters

URL: http://localhost:3000/api/v1/users/:userId/posts/:postId

# Postman auto-detects :params and shows them in the Params tab
# Fill in values:
userId  =  64abc123
postId  =  7

# Resolves to: http://localhost:3000/api/v1/users/64abc123/posts/7

Query parameters

URL: http://localhost:3000/api/v1/users

# In the Params tab, add key-value pairs:
Key       Value
---       -----
page      2
limit     20
sort      -createdAt
role      admin

# Resolves to: /api/v1/users?page=2&limit=20&sort=-createdAt&role=admin

Tip: You can toggle query params on/off with the checkbox next to each one — useful for testing different combinations.


6. Authorization in Postman

Bearer Token

Tab: Authorization
Type: Bearer Token
Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Postman automatically adds: Authorization: Bearer eyJhbG...

Basic Auth

Tab: Authorization
Type: Basic Auth
Username: admin
Password: secret123

Postman encodes to: Authorization: Basic YWRtaW46c2VjcmV0MTIz

API Key

Tab: Authorization
Type: API Key
Key:    X-API-Key
Value:  sk_live_abc123def456
Add to: Header (or Query Params)

Inherit from collection

Set authorization at the collection level and every request inherits it — no need to configure auth on each request individually.


7. Collections: Organizing Requests

Collections are folders of saved requests. They are essential for any non-trivial API.

Recommended structure

My API Collection/
  Auth/
    POST Register
    POST Login
    POST Refresh Token
    POST Logout
  Users/
    GET  List Users
    GET  Get User by ID
    POST Create User
    PUT  Update User
    DEL  Delete User
  Posts/
    GET  List Posts
    GET  Get Post by ID
    POST Create Post
    PATCH Update Post
    DEL  Delete Post
  Admin/
    GET  Dashboard Stats
    GET  All Users (admin)
    PUT  Ban User

Creating a collection

  1. Click + next to Collections in sidebar
  2. Name it (e.g., "My Blog API")
  3. Right-click -> Add Folder for each resource
  4. Drag requests into the appropriate folder
  5. Set collection-level authorization (Authorization tab on the collection)

8. Environment Variables

Environments let you switch between local, staging, and production without editing every request URL.

Setting up environments

Environment: Local Development
  base_url  =  http://localhost:3000
  token     =  (initially empty — set by login script)
  admin_id  =  64abc123

Environment: Staging
  base_url  =  https://staging-api.example.com
  token     =  (initially empty)
  admin_id  =  stage-admin-id

Environment: Production
  base_url  =  https://api.example.com
  token     =  (initially empty)
  admin_id  =  prod-admin-id

Using variables in requests

URL:     {{base_url}}/api/v1/users
Header:  Authorization: Bearer {{token}}
Body:    { "adminId": "{{admin_id}}" }

Variable scopes (highest to lowest priority)

ScopeLifetimeVisibility
Local (temporary)Current session onlyOnly you
EnvironmentPersisted, switchableWorkspace members
CollectionPersisted with collectionAnyone with the collection
GlobalPersisted across allWorkspace members

Setting variables from scripts

// In a "Login" request's Tests tab:
const response = pm.response.json();
pm.environment.set("token", response.token);
pm.environment.set("userId", response.user.id);
// Now {{token}} and {{userId}} are available in subsequent requests

9. Writing Tests in Postman

Postman uses a JavaScript-based scripting engine. Tests run after each request.

Basic test structure

// Tests tab of any request

// Test 1: Status code
pm.test("Status code is 200", function () {
  pm.response.to.have.status(200);
});

// Test 2: Response time
pm.test("Response time is under 500ms", function () {
  pm.expect(pm.response.responseTime).to.be.below(500);
});

// Test 3: Response body contains expected data
pm.test("Response has user data", function () {
  const json = pm.response.json();
  pm.expect(json.data).to.be.an('array');
  pm.expect(json.data.length).to.be.greaterThan(0);
});

// Test 4: Specific field validation
pm.test("First user has name and email", function () {
  const user = pm.response.json().data[0];
  pm.expect(user).to.have.property('name');
  pm.expect(user).to.have.property('email');
  pm.expect(user.email).to.include('@');
});

// Test 5: Header check
pm.test("Content-Type is JSON", function () {
  pm.response.to.have.header('Content-Type', /application\/json/);
});

Common pm.response assertions

AssertionWhat it checks
pm.response.to.have.status(201)Exact status code
pm.response.to.have.status("Created")Status text
pm.response.to.be.success2xx range
pm.response.to.be.clientError4xx range
pm.response.to.have.header('X-Custom')Header exists
pm.response.to.have.jsonBody('data')JSON body has key
pm.response.json()Parse response as JSON

Chaining requests: save data for next request

// In POST /login Tests tab:
pm.test("Login successful — save token", function () {
  pm.response.to.have.status(200);
  const json = pm.response.json();
  pm.environment.set("token", json.token);
  pm.environment.set("userId", json.user.id);
});

// Now GET /users/{{userId}} will use the real ID
// Authorization: Bearer {{token}} will use the real token

10. Pre-Request Scripts

Scripts that run before the request is sent. Useful for generating dynamic data.

// Generate a unique email for testing
const timestamp = Date.now();
pm.environment.set("testEmail", `testuser_${timestamp}@example.com`);

// Generate a UUID
const uuid = require('uuid');  // Postman includes uuid
pm.environment.set("requestId", uuid.v4());

// Set current timestamp
pm.environment.set("timestamp", new Date().toISOString());

// Generate HMAC signature for auth
const CryptoJS = require('crypto-js');
const secret = pm.environment.get("apiSecret");
const body = pm.request.body.raw;
const signature = CryptoJS.HmacSHA256(body, secret).toString();
pm.environment.set("signature", signature);

11. Collection Runner

The Collection Runner executes all requests in a collection (or folder) sequentially, running tests on each one.

How to use

  1. Click Runner in the top bar (or right-click a collection -> "Run collection")
  2. Select the collection or folder
  3. Choose the environment
  4. Set iterations (how many times to run the full sequence)
  5. Set delay between requests (0ms for speed, 100-500ms for realistic load)
  6. Click Run

Example workflow: full CRUD test

Order of execution:
  1. POST /auth/register  ->  saves {{token}} and {{userId}}
  2. GET  /users          ->  verifies user list contains new user
  3. GET  /users/{{userId}}  ->  verifies specific user
  4. PATCH /users/{{userId}} ->  updates name
  5. GET  /users/{{userId}}  ->  verifies name changed
  6. DELETE /users/{{userId}} ->  removes user
  7. GET  /users/{{userId}}  ->  verifies 404

Results panel

Run Results:
  POST Register       PASS  (201 Created, 45ms)
  GET List Users       PASS  (200 OK, 32ms)
  GET User by ID       PASS  (200 OK, 28ms)
  PATCH Update User    PASS  (200 OK, 35ms)
  GET Verify Update    PASS  (200 OK, 27ms)
  DELETE User          PASS  (204 No Content, 31ms)
  GET Verify Delete    PASS  (404 Not Found, 25ms)

  7/7 tests passed     Total time: 223ms

12. Exporting and Importing Collections

Export

  1. Right-click collection -> Export
  2. Choose format: Collection v2.1 (recommended)
  3. Save the .json file

Import

  1. Click Import in the top left
  2. Drag in the .json file, paste raw JSON, or link to a URL
  3. Postman creates the collection with all requests, tests, and variables

Team sharing patterns

MethodWhen to use
Export JSON + GitStore collection in your repo alongside code
Postman workspaceReal-time collaboration (team plan)
Public collection linkShare read-only with external developers
API documentationAuto-generate docs from collection
# Add to your project repo
project/
  docs/
    postman/
      My-API.postman_collection.json
      Local.postman_environment.json
      Staging.postman_environment.json

13. Thunder Client (VS Code Alternative)

If you prefer staying in VS Code, Thunder Client is a lightweight alternative.

FeaturePostmanThunder Client
PlatformStandalone app + webVS Code extension
CollectionsFull-featuredBasic but sufficient
Environment variablesAdvanced scopingSimple key-value
Test scriptsJavaScript (Chai)JavaScript (limited)
Team featuresWorkspaces, commentsGit-based sharing
Learning curveMediumLow
PriceFree tier + paidFree (paid for Git sync)

Install: Search "Thunder Client" in VS Code extensions.

Keyboard shortcut: Ctrl+Shift+R (open Thunder Client)

Recommendation: Start with Postman for learning (more resources, community). Consider Thunder Client if you prefer an all-in-VS-Code workflow.


14. Postman Workflow Cheat Sheet

1. Create a collection for your API
2. Set up environments (local, staging, production)
3. Use {{base_url}} in every request URL
4. Set collection-level auth (Bearer Token with {{token}})
5. Create a "Login" request that saves the token via Tests script
6. Organize requests into folders by resource
7. Write tests on each request (status code + body shape)
8. Use the Collection Runner to verify the entire flow
9. Export collection to JSON and commit to your repo
10. Share with teammates via workspace or Git

15. Key Takeaways

  1. Postman is the industry standard for manual and automated API testing during development.
  2. Environment variables ({{base_url}}, {{token}}) let you switch between local/staging/production instantly.
  3. Tests (pm.test()) and pre-request scripts turn Postman from a manual tool into an automated test suite.
  4. Collections organize requests logically and can be exported/imported as JSON for version control.
  5. The Collection Runner executes your entire API workflow in sequence, verifying all tests pass.

Explain-It Challenge

Explain without notes:

  1. How do environment variables in Postman help when switching between local and production APIs?
  2. Walk through how you would set up a login flow where the token from the login response is automatically used in all subsequent requests.
  3. What is the difference between pre-request scripts and tests in Postman?

Navigation: <- 3.9.b — API Versioning | 3.9.d — Status Codes in Practice ->