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
| Feature | Free Tier | Paid Tier |
|---|---|---|
| Request builder | Unlimited | Unlimited |
| Collections | Up to 25 per workspace | Unlimited |
| Environments | 5 per workspace | Unlimited |
| Collection runs | 25/month | Unlimited |
| Mock servers | 1,000 calls/month | Higher limits |
| Team collaboration | 3 members | Unlimited |
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
| Format | When to use | Content-Type |
|---|---|---|
| raw / JSON | Most API requests | application/json |
| form-data | File uploads, multipart forms | multipart/form-data |
| x-www-form-urlencoded | Simple form submissions | application/x-www-form-urlencoded |
| binary | Sending raw file bytes | Depends on file type |
| GraphQL | GraphQL queries | application/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
- Click + next to Collections in sidebar
- Name it (e.g., "My Blog API")
- Right-click -> Add Folder for each resource
- Drag requests into the appropriate folder
- 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)
| Scope | Lifetime | Visibility |
|---|---|---|
| Local (temporary) | Current session only | Only you |
| Environment | Persisted, switchable | Workspace members |
| Collection | Persisted with collection | Anyone with the collection |
| Global | Persisted across all | Workspace 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
| Assertion | What it checks |
|---|---|
pm.response.to.have.status(201) | Exact status code |
pm.response.to.have.status("Created") | Status text |
pm.response.to.be.success | 2xx range |
pm.response.to.be.clientError | 4xx 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
- Click Runner in the top bar (or right-click a collection -> "Run collection")
- Select the collection or folder
- Choose the environment
- Set iterations (how many times to run the full sequence)
- Set delay between requests (0ms for speed, 100-500ms for realistic load)
- 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
- Right-click collection -> Export
- Choose format: Collection v2.1 (recommended)
- Save the
.jsonfile
Import
- Click Import in the top left
- Drag in the
.jsonfile, paste raw JSON, or link to a URL - Postman creates the collection with all requests, tests, and variables
Team sharing patterns
| Method | When to use |
|---|---|
| Export JSON + Git | Store collection in your repo alongside code |
| Postman workspace | Real-time collaboration (team plan) |
| Public collection link | Share read-only with external developers |
| API documentation | Auto-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.
| Feature | Postman | Thunder Client |
|---|---|---|
| Platform | Standalone app + web | VS Code extension |
| Collections | Full-featured | Basic but sufficient |
| Environment variables | Advanced scoping | Simple key-value |
| Test scripts | JavaScript (Chai) | JavaScript (limited) |
| Team features | Workspaces, comments | Git-based sharing |
| Learning curve | Medium | Low |
| Price | Free tier + paid | Free (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
- Postman is the industry standard for manual and automated API testing during development.
- Environment variables (
{{base_url}},{{token}}) let you switch between local/staging/production instantly. - Tests (
pm.test()) and pre-request scripts turn Postman from a manual tool into an automated test suite. - Collections organize requests logically and can be exported/imported as JSON for version control.
- The Collection Runner executes your entire API workflow in sequence, verifying all tests pass.
Explain-It Challenge
Explain without notes:
- How do environment variables in Postman help when switching between local and production APIs?
- Walk through how you would set up a login flow where the token from the login response is automatically used in all subsequent requests.
- 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 ->