Postman and API testing at a QA interview: what to know and practise
Postman questions expose the gap between knowing API words and actually sending requests. The interviewer wants to see whether you can inspect a response, not just click Send.
- Method and URL
- Auth and headers
- Body and parameters
- Status, schema and data
What you should be able to do in Postman
Create a request, choose GET or POST, add query parameters, send JSON in the body, add an Authorization header and read the status code and response body.
For interviews, this is more important than advanced automation. A candidate who can reason about one response is stronger than one who memorised tab names.
The checks interviewers expect
For every API response check four layers: status code, structure, values and side effects. A 200 with the wrong total is still a bug; a 422 with the wrong field name is also a bug.
- Status code matches the situation.
- Required fields exist and have the right types.
- Important values match the request and requirements.
- Errors do not leak stack traces or internal paths.
- Repeated calls do not create accidental duplicates.
Auth checks in API testing
Always test the request with a valid token, without a token, with a broken token and with another user token. Many serious API defects hide in that last case.
If the endpoint returns data, ask whose data it is. Authentication only says who you are; authorization decides what you may see.
Typical Postman interview mistakes
The common mistakes are sending only happy-path requests, ignoring the body after seeing 200, forgetting headers and not saving the exact request that reproduced the defect.
A good habit: after every suspicious response, copy method, path, body and response into notes. That is already half of a bug report.
Practice task before the interview
Take any training API and test one endpoint with valid data, missing required field, wrong type, boundary value, no token and another user object id.
If you can explain each expected response and write one bug report from the result, you are ready for most junior Postman questions.
Real assertions in Tests
Each test should name the promise it protects. Separate assertions localise failures faster than one large block. Verify status and response type first, then schema and business values, and only then store an id for the next request.
The script below does not prove an order is fully correct, but it gives a useful minimum signal: valid JSON, required fields, a positive total and an id that can be chained safely.
pm.test("order created", () => pm.response.to.have.status(201));\n\nconst body = pm.response.json();\npm.test("contract and values", () => {\n pm.expect(body).to.have.property("id").that.is.a("number");\n pm.expect(body).to.have.property("status", "new");\n pm.expect(body.total).to.be.a("number").and.above(0);\n});\n\npm.collectionVariables.set("orderId", body.id);
Variables, chaining, Runner and CI
Use the narrowest scope: local for temporary secrets, data variables for a Runner row, environment for host values, collection for scenario data. Never commit live tokens in an exported collection. Tag created records uniquely and remove them in teardown when allowed.
- A pre-request script creates unique data or refreshes a token.
- Tests stores the response id only after validating the contract.
- The next request uses {{orderId}} and verifies the same object.
- Collection Runner repeats the flow with CSV or JSON data, including negative rows.
- Postman CLI or Newman runs the same collection in CI and exits non-zero on failure.
Follow-up questions interviewers ask
Be ready to explain why a 200-only test is weak, where a secret should live, how 401 and 403 differ, what happens when POST is retried after a timeout, and how to test pagination, rate limits and another user’s object id.
A strong candidate names the oracle: OpenAPI, an acceptance criterion, an RFC, a follow-up GET, database state or an agreed business rule. Without an oracle, a polished script merely freezes current behaviour.
Worked example: an order succeeds with the wrong total
Build one reproducible chain instead of unrelated requests: sign in, read the catalogue, add items, apply a promotion, create an order and read it back. Each step needs an independent expected result, not merely an HTTP status.
- Create isolated data and authenticate.
- Read the price and save product_id.
- Create the order and calculate its expected total.
- Read it back and inspect side effects.
Keep environment and data explicit
Keep base_url and a test token in an environment, but never publish secrets with a collection. Get product_id from the catalogue response rather than reusing an old item. Create a separate cart and user for independent runs; a shared account makes tests influence each other. Mark which values come from previous responses and which are fixed by the contract.
Check values as well as schema
A schema proves total is numeric, not correct. Two books at 690 RUB with a 10% discount should total 1,242 RUB if both items are eligible and rounding is specified. Compare catalogue price, order lines, discount, total and currency. If the formula or promotion order is not documented, clarify the contract rather than treating the observed response as truth.
Read after write
POST may return 201 with plausible JSON while the persisted order has a different total. Follow with GET /orders/{id}; if permitted, inspect storage and charge count. For an operation specified as idempotent, replay with the same key and check that no duplicate order appears. Do not assume every POST has that guarantee: it is a property of this particular API contract.
Make failures diagnostic
An assertion should show `expected_total=1242, actual_total=1380`, not just “test failed”. Group requests by scenario and clean data through an agreed method. In CI, use a separate environment and retain reports; distinguish expired tokens and shared-state failures from product defects.
const body = pm.response.json();\npm.test("created order has the agreed total", () => {\n pm.response.to.have.status(201);\n pm.expect(body.currency).to.eql("RUB");\n pm.expect(body.total).to.eql(1242);\n});\npm.environment.set("order_id", body.id);\n// Next: GET /orders/{{order_id}} and compare persisted total.
Where is the actual defect?
A 201 with total 1380 instead of 1242 under the approved rule is a functional defect even when the schema passes. If POST says 1242 but GET says 1380, persistence or reading is suspect. If both say 1242 while the charge is 1380, the issue is farther down the flow. These distinctions matter more than the tool name.
Second case: negative requests and API version compatibility
The happy path works. Now the team adds a required `delivery_address` to POST /orders, while an older mobile client never sends it. This tests not only body validation but backward compatibility during a staggered client/server rollout.
Map version combinations
Old client plus old server is the baseline. Old client plus new server is the main risk during server rollout. New client plus old server matters if the backend is rolled back after an app release. New plus new is normal operation. Ask which combinations are actually supported and how long old mobile versions remain active before dropping a row.
Distinguish validation from compatibility
For the new client, test omitted, null, empty, whitespace, overlong and wrong-type addresses. But an old client not knowing the field may now get 422, a regression despite the new schema being valid. A transition strategy might keep the field optional or obtain a saved profile address. The product chooses the strategy; QA exposes the conflict.
Check side effects of rejected input
A 422 should leave no order, stock reservation or charge when the contract promises atomicity. Correct the address and retry to detect a stranded partial order. A 400 instead of 422 is not automatically a bug: status and error shape follow the published API contract and team convention. Verify that the response identifies the field.
Follow data across layers
POST might echo the new address while the saved order keeps an old profile address. Read the order back, inspect the UI and downstream delivery event. One missing copy can surface only after payment. Carry a correlation id through the chain rather than deciding from a single POST response.
Protect the old consumer with a contract test
Add the old request to a collection or a consumer-driven contract for versions still supported. CI should prove the new server accepts the old payload and returns fields the old app uses. JSON Schema helps with structure but does not describe optional/default business semantics; record those decisions explicitly.
Client v1 + Server v1: baseline\nClient v1 + Server v2: missing address; follow support policy\nClient v2 + Server v1: rollback; unknown field handling\nClient v2 + Server v2: valid, missing, null, empty, wrong type\nRejected requests: no order, reservation or charge
What should the investigation produce?
A supported-version matrix, real requests from the old client, an agreed error contract and checks for absent side effects. That lets the team choose rollout order and a date for removing compatibility while QA writes reproducible checks.
Common Postman questions
Must a manual QA learn JavaScript for an interview?
Usually it is enough to read JSON, declare a const, access a field and write pm.test with pm.expect. Explaining what the assertion protects matters more. A specific role may require more.
Does Postman replace database verification?
No. An API exposes the external contract. A critical side effect may need a follow-up GET, event, database record or integration check.
How does Collection Runner differ from Newman or Postman CLI?
Runner executes interactively in Postman. A CLI runs the collection in a terminal and CI, where environments, reporters and exit codes matter. The assertions should stay the same.
Postman is not the skill by itself. The skill is noticing what the server actually promised and what it actually did.