What Is an API
An API (Application Programming Interface) is a contract that lets one program talk to another. A web API speaks HTTP: a client sends a request, the server sends back a response — usually carrying JSON data.
REST (Representational State Transfer) is the most common style for designing such APIs. It is not a protocol or a library — it is a set of rules for how to shape the URLs, methods and responses. HTTP transfers the data; REST says how to organize it.
The central idea is the resource: every thing your API manages — a user, an order, a photo — has its own URL, like /users/7.
The Rules of REST
REST rests on a few principles:
Client–server — the two sides are separate and evolve separately.
Stateless — every request carries everything the server needs; the server remembers nothing between requests.
Uniform interface — the same URLs, methods and status codes mean the same things everywhere.
Cacheable — responses can say "you may reuse this answer", saving round trips.
Layered — proxies, gateways and load balancers can sit between client and server without either noticing.
One Request, One Response
Every API interaction is this cycle: a request (method + URL + optional body) goes out, a response (status code + headers + body) comes back. Here is one full round trip in TypeScript — the demo starts a tiny local server so the program can run and finish on its own.
A full round trip
The client asks GET /users/1; the server answers with status 200 OK, a content type, and a JSON body. Every page in this group builds on this cycle.
Output: TypeScript file and captured output
import { createServer } from "node:http"
async function main(): Promise<void> {
// A tiny local server for the demo. Port 0 means "any free port",
// so the example never clashes with something already running.
const server = createServer((req, res) => {
res.writeHead(200, { "Content-Type": "application/json" })
res.end('{"id": 1, "name": "Ana"}')
})
await new Promise<void>(resolve => server.listen(0, () => resolve()))
const port = (server.address() as { port: number }).port
const res = await fetch(`http://localhost:${port}/users/1`)
const body = await res.text()
console.log("request: GET /users/1")
console.log("status: ", res.status, res.statusText)
console.log("type: ", res.headers.get("content-type"))
console.log("body: ", body)
server.close()
}
main()
Methods, Status Codes and Limits
The HTTP methods map onto the four data operations (CRUD):
GET read a resource · POST create one · PUT replace one · PATCH change part of one · DELETE remove one.
Status codes tell how it went: 200 OK, 201 Created, 204 No Content, 400 Bad Request, 401 Unauthorized, 404 Not Found, 500 Internal Server Error.
And REST has honest limits: it is not built for real-time streams, a response may carry more or less than the client wanted, and versioning a public API takes discipline. Knowing the limits is part of knowing the style.