How an API Works: Request, Response and Endpoints Explained
Before you can test an API you need to see exactly what travels between the app and the server. In this lesson we follow one food order from the moment you tap “Place Order” until the confirmation appears, then break every API request and response into its parts: URL, method, headers, body, status code. Every concept is shown on a live endpoint you can call right now.
The Client-Server Model in Plain Words
Every API conversation has two sides:
- Client: whoever asks. It can be a mobile app, a website running in the browser, Postman, a Playwright test, or another backend service.
- Server: whoever answers. It receives the request, checks who you are, applies business rules, reads or writes the database, and replies.
The client and server can be written in totally different languages. A Swift iPhone app can talk to a Java server, which can talk to a Python pricing service. They understand each other because they agree on the same HTTP protocol and data format (usually JSON).
Step-by-Step: What Happens When You Place a Food Order
- You tap Place Order. The app builds a request:
POST https://api.foodapp.com/v1/orderswith your token in theAuthorizationheader and the items in a JSON body. - DNS converts
api.foodapp.cominto an IP address. - A secure HTTPS (TLS) connection is opened so nobody on the Wi-Fi can read the data.
- An API gateway checks the token and the rate limit, then forwards the request to the order service.
- The order service validates the items, asks the pricing service for the total, reserves stock and saves the order in the database.
- The server replies
201 Createdwith the new order id and total. - The app reads the JSON and shows “Order placed! Arriving in 32 minutes.”
As a tester, steps 1 and 6 are what you control and observe. Everything in between is the “black box” you are testing through its API.
Anatomy of an API URL
Take this real endpoint from the SQA Tools practice API:
https://sqatools.in/wp-json/sqa-api/v1/users?role=admin&sort=age&order=desc
| Part | Value | Meaning |
|---|---|---|
| Scheme | https | Protocol; HTTPS means encrypted |
| Host (domain) | sqatools.in | Which server to call |
| Base path | /wp-json/sqa-api | Where this API lives on the server |
| Version | /v1 | API version, so old apps keep working when v2 arrives |
| Resource | /users | The “thing” you work with (a noun, plural) |
| Query string | ?role=admin&sort=age&order=desc | Optional filters, sorting and paging |
Everything up to and including the version is called the base URL: https://sqatools.in/wp-json/sqa-api/v1. Each resource path added to it, together with a method, is an endpoint.
Endpoint = Method + Path
The same path can be several endpoints, depending on the HTTP method:
| Endpoint | What it does |
|---|---|
GET /objects | List objects |
POST /objects | Create a new object |
GET /objects/{id} | Read one object |
PUT /objects/{id} | Replace it completely |
PATCH /objects/{id} | Change some fields |
DELETE /objects/{id} | Delete it |
The {id} part is a path parameter. You will study path and query parameters in depth in this lesson.
The 4 Parts of an API Request
1. Method (verb)
Tells the server what you want to do: GET read, POST create, PUT replace, PATCH update, DELETE remove. Full details in HTTP Methods.
2. URL (where)
Base URL + resource path + optional query string.
3. Headers (extra information about the request)
Content-Type: application/json (the body I am sending is JSON)
Accept: application/json (please answer in JSON)
Authorization: Bearer eyJhbGciOi... (this is who I am)
X-Request-Id: 7f3c-91aa (trace id for debugging)
4. Body (payload, the data you send)
Used with POST, PUT and PATCH. GET and DELETE normally have no body.
{
"name": "Laptop bag",
"data": { "color": "black", "qty": 1 },
"ttl": 120
}
The 3 Parts of an API Response
1. Status code
A 3-digit number that summarises the result. 2xx success, 3xx redirect, 4xx your (client) mistake, 5xx server failure. See the complete status code list.
2. Response headers
For example Content-Type, Location (URL of a newly created item), ETag (version for caching), Retry-After, and pagination headers such as X-Total-Count.
3. Response body
The data itself, or an error object. The practice API always uses the same error format, which is good API design and easy to assert:
{
"error": {
"status": 404,
"code": "not_found",
"message": "User 999 does not exist. Valid ids are 1 to 12."
}
}
See a Full Request and Response Live
Press Send request to create a temporary object (it deletes itself after 2 minutes). Look at the status 201, the Location header and the ETag header in the result.
https://sqatools.in/wp-json/sqa-api/v1/objectscurl -i \
-X POST \
-H "Content-Type: application/json" \
-d '{"name":"Laptop bag","data":{"color":"black","qty":1},"ttl":120}' \
"https://sqatools.in/wp-json/sqa-api/v1/objects"Here is the same conversation written out as raw HTTP, which is how it really looks on the wire:
POST /wp-json/sqa-api/v1/objects HTTP/1.1
Host: sqatools.in
Content-Type: application/json
Accept: application/json
{"name":"Laptop bag","data":{"color":"black","qty":1},"ttl":120}
HTTP/1.1 201 Created
Content-Type: application/json; charset=UTF-8
Location: https://sqatools.in/wp-json/sqa-api/v1/objects/obj_hoeovqif1v
ETag: "v1"
{"id":"obj_hoeovqif1v","name":"Laptop bag","data":{"color":"black","qty":1},
"version":1,"created_at":"2026-11-12T08:03:29Z","ttl_seconds":120, ...}
Location header exists and ends with the returned id. version is 1. name and data match what you sent. A follow-up GET on the Location URL returns the same object. Sending the same body without name returns 422.Writing the Same Request in Code
cURL
curl -i -X POST "https://sqatools.in/wp-json/sqa-api/v1/objects" \
-H "Content-Type: application/json" \
-d '{"name":"Laptop bag","data":{"color":"black","qty":1},"ttl":120}'
The -i flag prints response headers, which testers almost always want to see.
Playwright with TypeScript
import { test, expect } from '@playwright/test';
const BASE = 'https://sqatools.in/wp-json/sqa-api/v1';
test('create an object and read it back', async ({ request }) => {
// 1. Request: method + URL + headers + body
const create = await request.post(`${BASE}/objects`, {
data: { name: 'Laptop bag', data: { color: 'black', qty: 1 }, ttl: 120 },
});
// 2. Response: status, headers, body
expect(create.status()).toBe(201);
const location = create.headers()['location'];
const created = await create.json();
expect(location).toContain(created.id);
expect(created.version).toBe(1);
// 3. Prove it was saved: GET the Location URL
const read = await request.get(location);
expect(read.ok()).toBeTruthy();
expect((await read.json()).name).toBe('Laptop bag');
});
Passing an object to data makes Playwright set Content-Type: application/json automatically.
Synchronous vs Asynchronous APIs
Most REST calls are synchronous: you wait and get the result in the same response. Some work takes too long, like generating a 50-page bank statement. Then the API is asynchronous:
POST /statementsreturns202 Acceptedwith a job id.- The client polls
GET /statements/jobs/{id}until the status is"done", or the server calls the client back with a webhook.
Testing async APIs means checking the 202, the job status changes, timeouts and the final result. We cover webhooks in a later module.
Stateless: Why Every Request Must Carry Everything
REST APIs are stateless: the server does not remember your previous request. That is why your token goes in every request header. For testers this means:
- Each test can be run alone, in any order, which makes parallel automation easy.
- If a test passes only after another test ran first, it has a hidden dependency. Create your own test data inside each test instead.
Common Mistakes Beginners Make
- Checking only the status code and not the body. A
200with the wrong total is still a bug. - Forgetting
Content-Type: application/jsonwhen sending a JSON body by hand (cURL). The practice API answers415 Unsupported Media Type. - Mixing up the base URL and the endpoint path, or adding double slashes.
- Not verifying that a create or update was really saved with a follow-up GET.
- Hardcoding ids that another tester or test run may delete.
Interview Questions: How APIs Work
Explain the request-response cycle of an API.
The client sends an HTTP request containing a method, URL, headers and an optional body to an endpoint. The server authenticates it, runs business logic, reads or writes data and returns a response with a status code, headers and a body. Each cycle is independent because REST is stateless.
What is the difference between a base URL, a resource and an endpoint?
The base URL is the common root such as https://sqatools.in/wp-json/sqa-api/v1. A resource is the noun being managed, such as /users. An endpoint is a method plus a full path, such as GET /users/1.
What are the main parts of an HTTP request?
Method, URL (including path and query parameters), headers and an optional body. The protocol version is also part of the request line.
What are the main parts of an HTTP response?
A status line with the status code, response headers and an optional body. Some responses such as 204 No Content and 304 Not Modified have no body.
What does stateless mean in REST?
The server keeps no client session between requests. Every request must contain all information needed to process it, including authentication. This makes APIs scalable and makes tests independent.
What is the role of an API gateway?
An API gateway is the single entry point in front of many services. It handles authentication, rate limiting, routing, logging and sometimes caching. Testers often see 401, 429 or 502 errors coming from the gateway rather than from the service.
What is the difference between synchronous and asynchronous APIs?
A synchronous API returns the final result in the same response. An asynchronous API accepts the work (often 202 Accepted), returns a job id, and the client polls or receives a webhook when the job finishes.
Why does a POST that creates a resource usually return a Location header?
The Location header gives the URL of the new resource, so the client can fetch it without building the URL. Testers should assert it exists, points to the new id and returns the same data on GET.
How do you verify that a POST actually saved data?
Check the 201 status and returned body, then call GET on the new resource (or list endpoint) and compare the stored values. Optionally verify in the database if you have access.
What is API documentation and which format is common?
API documentation lists endpoints, parameters, request and response examples, error codes and authentication. The most common format is the OpenAPI Specification, often displayed with Swagger UI.