Modern applications are built in layers. The screen you tap on a mobile app is only the front end; behind it, the app talks to servers through APIs. Testing at the API layer finds defects earlier, runs faster than UI testing and is a skill that appears in a large share of QA job descriptions in India. This lesson takes you from zero to writing your first automated checks in Postman.
What Is an API?
An API (Application Programming Interface) is a contract that lets one piece of software request data or actions from another. Think of a restaurant: you (the client) do not walk into the kitchen (the server); you give your order to the waiter (the API), who brings back your food (the response). When you check your train PNR status in an app, the app sends an API request to the server and displays the data it receives.
REST in Brief
REST is the most common style for web APIs. REST APIs expose resources (users, orders, bookings) at URLs called endpoints, use standard HTTP methods to act on them, are stateless (each request carries everything the server needs, such as an auth token), and usually exchange data in JSON.
HTTP Methods
| Method | Purpose | Example |
|---|---|---|
| GET | Read data | GET /api/orders/5012 |
| POST | Create a new resource | POST /api/orders |
| PUT | Replace a resource completely | PUT /api/users/77 |
| PATCH | Update part of a resource | PATCH /api/users/77 (only phone number) |
| DELETE | Remove a resource | DELETE /api/cart/items/3 |
Status Codes Every Tester Must Know
| Code | Meaning | When you see it |
|---|---|---|
| 200 OK | Request succeeded | Successful GET, PUT or PATCH |
| 201 Created | New resource created | Successful POST that creates an order |
| 204 No Content | Success with no body | Successful DELETE |
| 400 Bad Request | Invalid input | Missing field or wrong format |
| 401 Unauthorized | Not authenticated | Missing or expired token |
| 403 Forbidden | Authenticated but not allowed | Customer calls an admin-only endpoint |
| 404 Not Found | Resource does not exist | Order ID that was never created |
| 409 Conflict | State conflict | Registering an email that already exists |
| 500 Internal Server Error | Server-side failure | Unhandled exception; almost always a bug |
| 503 Service Unavailable | Server temporarily down | Maintenance or overload |
Anatomy of a Request and Response
A request has a method, a URL (with optional path and query parameters such as ?status=confirmed), headers (metadata such as Content-Type: application/json and Authorization: Bearer <token>) and, for POST/PUT/PATCH, a body. A response has a status code, headers and usually a JSON body. Here is a request body for creating an order:
{
"userId": 77,
"items": [
{ "productId": "P-1001", "qty": 2, "price": 499 }
],
"paymentMode": "UPI",
"couponCode": "SAVE100"
}And a typical response with status 201 Created:
{
"orderId": "ORD-58213",
"status": "CONFIRMED",
"totalAmount": 898,
"createdAt": "2026-03-14T10:22:05Z"
}Working in Postman
- Collections: folders of saved requests, e.g. "Shop API" with sub-folders Auth, Cart and Orders. Collections can be shared with the team and run together with the Collection Runner.
- Environments: sets of variables for each server, such as QA and Staging, so the same requests work everywhere.
- Variables: placeholders written as
{{baseUrl}}or{{token}}. Scopes include global, collection, environment and local.
Create an environment "QA" with baseUrl = https://qa.shop.example/api. Your request URL becomes {{baseUrl}}/orders. To test on staging, just switch the environment; no request needs editing.
Writing Tests in Postman
Postman runs JavaScript in the Tests tab (labelled Post-response scripts in newer versions) after each response. The pm object gives you access to the response and assertion helpers.
pm.test("Status code is 201", function () {
pm.response.to.have.status(201);
});
pm.test("Response time is below 800 ms", function () {
pm.expect(pm.response.responseTime).to.be.below(800);
});
pm.test("Content-Type is JSON", function () {
pm.expect(pm.response.headers.get("Content-Type")).to.include("application/json");
});
const body = pm.response.json();
pm.test("Order is confirmed with correct total", function () {
pm.expect(body.orderId).to.be.a("string");
pm.expect(body.status).to.eql("CONFIRMED");
pm.expect(body.totalAmount).to.eql(898);
});
// Save the order ID for the next request in the collection
pm.environment.set("orderId", body.orderId);A login request can save the token the same way, so every later request sends Authorization: Bearer {{token}} automatically:
pm.environment.set("token", pm.response.json().accessToken);What to Validate in API Testing
- Status code matches the scenario (201 for create, 400 for bad input).
- Response body: correct values, data types, mandatory fields present, no extra sensitive data such as passwords.
- Headers: content type, caching and security headers.
- Negative cases: missing fields, wrong types, invalid IDs, expired token (expect 401), wrong role (expect 403).
- Business rules: coupon applied, stock reduced, duplicate order prevented.
- Response time within the agreed limit.
- Data persistence: a follow-up GET, or a database query, confirms the data was actually saved.
Many beginners stop at checking the status code. An API can return 200 with a wrong amount or an empty list. Always validate the body against the requirement.