Practice Postman Fundamentals
This is Part 1 of the Postman API Testing Roadmap: understanding an API before testing it, organizing Postman like a real team, and working through every HTTP method with test scripts. The practice API is Restful Booker. The CRUD scripts below were run with Newman against a local booking API built the same way — all 12 assertions passed.
1. Understand the API First
Exercises
- List every endpoint from the documentation.
- Mark which are public and which need authentication.
- Map dependencies — which calls need a value from another.
- Decide what to test first (business-critical flows).
- Open the browser's DevTools → Network tab, use the app, and match UI actions to API calls.
- List business rules the API must enforce (required fields, valid dates, prices).
- Split the endpoints into smoke and regression sets.
Worked example: Restful Booker
| Endpoint | Auth | Depends on | Smoke? |
|---|---|---|---|
GET /ping |
Public | — | ✅ health check |
POST /auth |
Public | — | ✅ |
GET /booking, GET /booking/{id} |
Public | An existing booking | ✅ |
POST /booking |
Public | — | ✅ |
PUT, PATCH /booking/{id} |
Token (cookie) | Auth, a booking | Regression |
DELETE /booking/{id} |
Token (cookie) | Auth, a booking | Regression |
The dependency flow: auth → token → update/delete, and create → bookingid → read/update/delete. Knowing this before you open Postman tells you which variables your collection needs. Plan full positive, negative and edge cases per endpoint in the API Testing Scenario Lab.
2. Set Up Postman Like a Team
Exercises
- Create a workspace for the project (shared with the team in real work).
- Create environments — QA, Staging — each with
baseUrland credentials. - Create a collection with folders by module and purpose.
- Agree a naming convention.
- Import an OpenAPI/Swagger file to generate requests automatically (try the Petstore spec).
- Add descriptions and saved examples so the collection documents the API.
- Export the collection to Git, or use Postman's version control, so changes are reviewed.
Restful Booker (collection)
├── 00 Health GET Ping
├── 01 Auth POST Create token
├── 02 Booking CRUD POST Create booking · GET Get booking · PUT Update booking
│ PATCH Update price · DELETE Delete booking · GET Get deleted booking (404)
└── 03 Negative POST Missing firstname · POST Wrong content type · PUT No token
Naming: start with the verb and intent — "Create booking — missing firstname" — so a failure in a Newman report explains itself. More on scopes and secrets: Postman Environments & Variables.
3. HTTP Methods — CRUD With Test Scripts ⭐
Each request below shows its Post-response (Tests) script. Run the folder in order with the Collection Runner.
Auth — POST /auth
// Body: { "username": "admin", "password": "{{password}}" }
pm.test('200 and token', () => {
pm.response.to.have.status(200);
pm.expect(pm.response.json().token).to.be.a('string');
});
pm.collectionVariables.set('token', pm.response.json().token);
Create — POST /booking
// Pre-request: unique data every run
pm.variables.set('firstname', 'QA_' + Date.now());
// Body: { "firstname": "{{firstname}}", "lastname": "Rao", "totalprice": 150, "depositpaid": true,
// "bookingdates": { "checkin": "2026-11-01", "checkout": "2026-11-04" } }
// Tests
const b = pm.response.json();
pm.test('created', () => pm.expect(pm.response.code).to.be.oneOf([200, 201])); // Restful Booker returns 200
pm.test('id returned', () => pm.expect(b.bookingid).to.be.a('number'));
pm.test('name echoed', () => pm.expect(b.booking.firstname).to.eql(pm.variables.get('firstname')));
pm.collectionVariables.set('bookingId', b.bookingid);
Read — GET /booking/{{bookingId}}
pm.test('200', () => pm.response.to.have.status(200));
pm.test('data matches', () => pm.expect(pm.response.json()).to.include({ lastname: 'Rao', totalprice: 150 }));
Update — PUT /booking/{{bookingId}}
// Header: Cookie: token={{token}} (Restful Booker; most APIs use Authorization: Bearer)
// Body: the full booking with "totalprice": 200
pm.test('200', () => pm.response.to.have.status(200));
pm.test('price updated', () => pm.expect(pm.response.json().totalprice).to.eql(200));
PATCH works the same way with only the changed fields — then add a test that a field you didn't send (such as lastname) is unchanged. That's the real difference between PUT and PATCH, and a common bug: a "partial" update that wipes the other fields.
Delete and verify — DELETE, then GET
// DELETE /booking/{{bookingId}}
pm.test('deleted', () => pm.expect(pm.response.code).to.be.oneOf([200, 201, 204])); // Restful Booker: 201
// GET /booking/{{bookingId}}
pm.test('404 after delete', () => pm.response.to.have.status(404));
Negative checks
// POST /booking with body { "totalprice": 10 }
pm.test('400 for missing firstname', () => pm.response.to.have.status(400));
// POST /booking with Content-Type: text/plain
pm.test('415 for text/plain', () => pm.response.to.have.status(415));
A public practice API won't always return the "textbook" code — Restful Booker, for example, answers some invalid bodies with 500. Record what the API does, compare it with what it should do, and treat a 500 for bad input as a bug to report. That judgment is the point of the exercise. More: HTTP Methods & Status Codes.
Method validation
- Send a method an endpoint doesn't support (for example DELETE on
/ping) — expect405(or404, as documented). - Send PUT without a token — expect
401/403. - Send the same PUT twice — the result should be identical (idempotent).
4. Request Data Exercises
| Exercise | How to do it in Postman |
|---|---|
| Query parameters | GET /booking?firstname=Asha&lastname=Rao — use the Params tab |
| Path parameters | /booking/{{bookingId}} or /booking/:id with the Path Variables table |
| Mandatory vs optional | Remove one field at a time; required ones should fail, optional ones get defaults |
| Nested JSON | bookingdates object inside the booking |
| Dynamic values | {{$randomFirstName}}, {{$randomInt}}, {{$isoTimestamp}} |
| Headers | Wrong Accept or Content-Type; missing auth |
| Special characters | O'Brien, José, emoji — stored and returned exactly |
| Large payloads | A 10,000-character name — rejected cleanly, never a 500 |
Next: Part 2 — Token Handling and Part 3 — Assertions.
From Real Projects
My API testing experience covers CRUD operations, HTTP methods, JSON path, and validating JSON and XML data. On Testsigma, a platform that itself automates API tests, understanding requests, responses and status codes was part of understanding the product. Whatever tool you use, validate the status code, the response structure and the values — not just that the call returned something. Map every endpoint and its dependencies before writing tests. You may also find The Complete API Testing Tutorial useful.
FAQs
What should you analyze before testing an API?
Endpoints, authentication, dependencies between calls, business rules, and which flows are critical enough for smoke tests.
How should a Postman project be organized?
One workspace per project, environments per target system, a collection with folders by module and purpose, clear request names, and documentation with examples.
How do you pass a created ID to later requests?
Save it in the create request's tests (pm.collectionVariables.set('bookingId', …)) and use {{bookingId}} in the URL of later requests.
How do you test PUT vs PATCH?
PUT sends the whole resource; PATCH sends only changed fields — then verify that fields you didn't send are unchanged. See also: Top 30 API Testing Interview Questions & Answers.
What should an unsupported method return?
405 Method Not Allowed is the standard; some APIs return 404 — test what the documentation promises.
Related