Developer Education Series

APIs: The Complete Guide

What an API really is, the major types, how to design and build one from scratch, how to connect your application to someone else's, plus versioning, security, architecture, caching, real-time patterns, and beginner-friendly glossaries โ€” everything you need in one place.

๐ŸŒ Fundamentals ๐Ÿงฉ 8 API types ๐Ÿ” Security & OWASP ๐Ÿ—๏ธ Architecture patterns โšก Caching & real-time ๐Ÿ“– Glossaries for beginners

01 What is an API?

API stands for Application Programming Interface. It is a contract that lets two pieces of software talk to each other without either one needing to know how the other is built internally.

Think of a restaurant. You (the client) don't walk into the kitchen and cook. You tell the waiter what you want from a menu, the kitchen (the server) prepares it, and the waiter brings back exactly what you ordered. The menu is the API: a defined list of things you can ask for, and the format you must ask in.

ClientBrowser, mobile app, script
โ†’
RequestEndpoint + method + data
โ†’
API LayerValidates, routes, authorizes
โ†’
Server / DBBusiness logic, data
โ†’
ResponseJSON + status code

Why APIs matter

๐Ÿ”— Decoupling

Frontend and backend evolve independently as long as the contract holds.

โ™ป๏ธ Reusability

One API can serve a web app, an iOS app, a partner, and internal scripts.

๐Ÿ”’ Security

You expose only specific operations โ€” never your database directly.

๐Ÿ“ˆ Scalability

Services can be scaled, cached, and rate-limited independently.

Key idea

An API is an abstraction boundary. It hides complexity and exposes capability.

02 Anatomy of an API Request

Every HTTP API call has the same five ingredients. Learn these and every API becomes readable.

PartWhat it isExample
Method The verb โ€” what action you want GET POST
URL / Endpoint The address of the resource https://api.shop.com/v1/products/42
Headers Metadata: auth, content type, caching Authorization: Bearer โ€ฆ
Query params Filters, pagination, sorting (in the URL) ?page=2&limit=20&sort=price
Body The payload you send (POST/PUT/PATCH) {"name":"Laptop","price":999}

A real request, decoded

POST /v1/products?notify=true HTTP/1.1
Host: api.shop.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Content-Type: application/json
Accept: application/json

{
  "name": "Mechanical Keyboard",
  "price": 129.99,
  "tags": ["hardware", "input"]
}

And the response

HTTP/1.1 201 Created
Content-Type: application/json
Location: /v1/products/1087

{
  "id": 1087,
  "name": "Mechanical Keyboard",
  "price": 129.99,
  "createdAt": "2025-01-14T09:22:31Z"
}
Tip

Idempotency matters: calling GET, PUT, or DELETE twice should leave the system in the same state as calling it once. POST is not idempotent โ€” two calls usually create two records.

03 Types of APIs

APIs are classified in two useful ways: by architecture/protocol and by audience.

A. By architecture & protocol

REST

Resource-oriented, uses standard HTTP verbs and JSON. The default choice for most web APIs.

GraphQL

Single endpoint, client specifies exactly which fields it needs. Great for complex, nested data.

SOAP

XML-based, strict contract via WSDL. Still common in banking, healthcare, and legacy enterprise.

gRPC

Binary Protocol Buffers over HTTP/2. Very fast, strongly typed, ideal for internal microservices.

WebSocket

Persistent, full-duplex connection. Perfect for chat, live dashboards, collaborative editing.

Webhooks

Reverse APIs โ€” the server calls you when an event happens. No polling needed.

RPC / JSON-RPC

Call a remote function by name. Simple and direct, less resource-oriented than REST.

SSE (Server-Sent Events)

One-way streaming from server to client over plain HTTP. Simpler than WebSockets for feeds.

B. By audience

TypeWho uses itExample
Public / OpenAnyone, often with a key or free tierOpenWeather, Stripe, GitHub
PartnerSpecific vetted businessesAirline booking partners
Private / InternalOnly your own teamsMicroservice-to-microservice
CompositeAggregates several APIs into oneA dashboard mashing weather + maps + news
Rule of thumb

Start with REST + JSON unless you have a specific reason not to. Choose GraphQL when clients need flexible queries, gRPC for high-performance internal calls, and WebSockets when you need real-time push.

04 HTTP Methods (Verbs)

REST maps actions onto standard HTTP methods. Using them correctly makes your API predictable.

MethodPurposeIdempotent?Has body?Example
GET Read a resource or collection YesNo GET /books
POST Create a new resource NoYes POST /books
PUT Replace a resource entirely YesYes PUT /books/7
PATCH Update part of a resource No*Yes PATCH /books/7
DELETE Remove a resource YesRarely DELETE /books/7

*PATCH can be made idempotent depending on the operations used.

Less-common but useful methods

  • HEAD โ€” same as GET but returns only headers (check existence, size, or last-modified).
  • OPTIONS โ€” asks what methods a resource supports. Browsers use it for CORS preflight.
  • TRACE โ€” echoes the request back; almost never used, often disabled for security.
  • CONNECT โ€” establishes a tunnel (e.g. HTTPS through a proxy).

05 HTTP Status Codes

The three-digit number in every response tells the client what happened โ€” without reading the body.

RangeMeaningCommon codes
1xxInformational101 Switching Protocols
2xxSuccess200 OK, 201 Created, 202 Accepted, 204 No Content
3xxRedirection301 Moved Permanently, 304 Not Modified
4xxClient error โ€” you messed up400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 409 Conflict, 422 Unprocessable Entity, 429 Too Many Requests
5xxServer error โ€” they messed up500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable, 504 Gateway Timeout
Common confusion

401 Unauthorized actually means "unauthenticated" (we don't know who you are). 403 Forbidden means "authenticated but not allowed" (we know who you are, and no).

Returning errors consistently

{
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "The 'price' field must be a positive number.",
    "field": "price",
    "requestId": "req_8f2a91c"
  }
}
Good error messages

A great error tells the client what went wrong, where, and how to fix it โ€” without leaking stack traces or database internals.

06 Authentication & Authorization

Authentication = who are you? Authorization = what are you allowed to do?

๐Ÿ”‘ API Keys

Simple shared secret sent in a header. Easy to start, hard to rotate, no user context.

๐Ÿงพ Basic Auth

Base64 of user:password. Only acceptable over HTTPS. Legacy but simple.

๐ŸŽซ JWT (Bearer)

Signed, self-contained token with claims. Stateless โ€” great for distributed systems.

๐Ÿ”„ OAuth 2.0

Delegated access without sharing passwords. "Sign in with Google" is built on this.

๐Ÿชช OIDC

OAuth 2.0 plus an identity layer. Adds a standard id_token with user info.

๐Ÿ” mTLS

Both client and server present certificates. Common in zero-trust internal networks.

Sending credentials

# API key (header)
X-API-Key: sk_live_9f8a7b6c5d

# Bearer token (JWT or OAuth access token)
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

# HTTP Basic
Authorization: Basic dXNlcjpwYXNzd29yZA==

The OAuth 2.0 Authorization Code flow

1. RedirectApp โ†’ Auth server
โ†’
2. ConsentUser logs in & approves
โ†’
3. CodeAuth server โ†’ App callback
โ†’
4. ExchangeCode โ†’ access token
โ†’
5. Call APIWith Bearer token

JWT structure โ€” three Base64 parts

header.payload.signature

# Decoded payload example
{
  "sub": "user_42",
  "scope": "read:books write:books",
  "iat": 1705312800,
  "exp": 1705316400
}
Never do this

Never put secrets in client-side JavaScript, query strings, or a public Git repo. Query strings get logged by proxies and browsers. Ship secrets only in server-side environment variables.

07 How to Build an API

Here is the end-to-end process, followed by two complete working examples.

The 7-step process

  1. Define the use cases. What will clients actually need to do? List them as user stories.
  2. Model the resources. Nouns become endpoints: /users, /orders, /orders/42/items.
  3. Design the contract. Choose URLs, methods, request/response shapes, and error formats. Write it down (OpenAPI/Swagger).
  4. Pick a stack. Node/Express, Python/FastAPI, Go/Fiber, Java/Spring, Ruby/Rails โ€” any is fine.
  5. Implement + validate. Parse and validate every input. Never trust the client.
  6. Add cross-cutting concerns. Auth, rate limiting, logging, error handling, CORS, versioning.
  7. Document, test, deploy, monitor. Automate tests, ship behind HTTPS, watch latency and error rates.

Example A โ€” Node.js + Express

server.js
const express = require('express');
const app = express();

app.use(express.json());   // parse JSON bodies

// In-memory "database" for the demo
let books = [
  { id: 1, title: 'The Pragmatic Programmer', author: 'Hunt & Thomas' }
];
let nextId = 2;

// ---------- READ ALL ----------
app.get('/api/books', (req, res) => {
  res.json({ data: books, count: books.length });
});

// ---------- READ ONE ----------
app.get('/api/books/:id', (req, res) => {
  const book = books.find(b => b.id === Number(req.params.id));
  if (!book) {
    return res.status(404).json({ error: 'Book not found' });
  }
  res.json(book);
});

// ---------- CREATE ----------
app.post('/api/books', (req, res) => {
  const { title, author } = req.body;

  // Validation: never trust the client
  if (!title || typeof title !== 'string') {
    return res.status(400).json({ error: 'title is required' });
  }

  const book = { id: nextId++, title, author: author || 'Unknown' };
  books.push(book);
  res.status(201).json(book);
});

// ---------- UPDATE (partial) ----------
app.patch('/api/books/:id', (req, res) => {
  const book = books.find(b => b.id === Number(req.params.id));
  if (!book) return res.status(404).json({ error: 'Book not found' });

  Object.assign(book, req.body);
  res.json(book);
});

// ---------- DELETE ----------
app.delete('/api/books/:id', (req, res) => {
  const before = books.length;
  books = books.filter(b => b.id !== Number(req.params.id));
  if (books.length === before) {
    return res.status(404).json({ error: 'Book not found' });
  }
  res.status(204).send();
});

app.listen(3000, () => console.log('API running on http://localhost:3000'));

Example B โ€” Python + FastAPI

main.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

app = FastAPI(title="Books API", version="1.0")


class BookIn(BaseModel):
    title: str
    author: str = "Unknown"


class Book(BookIn):
    id: int


books: list[Book] = [Book(id=1, title="Dune", author="Herbert")]


@app.get("/api/books")
def list_books():
    return {"data": books, "count": len(books)}


@app.get("/api/books/{book_id}")
def get_book(book_id: int):
    for b in books:
        if b.id == book_id:
            return b
    raise HTTPException(status_code=404, detail="Book not found")


@app.post("/api/books", status_code=201)
def create_book(payload: BookIn):
    new_id = max((b.id for b in books), default=0) + 1
    book = Book(id=new_id, **payload.model_dump())
    books.append(book)
    return book

# Run with:  uvicorn main:app --reload
# Free interactive docs at  http://localhost:8000/docs
FastAPI bonus

FastAPI generates OpenAPI documentation automatically from your type hints โ€” you get a live, clickable API console for free.

08 Designing Clean Endpoints

โœ… Do

  • Use plural nouns for collections: /users, not /getUser.
  • Use nesting for real ownership: /users/42/orders.
  • Use query parameters for filtering, sorting, and pagination.
  • Version your API from day one: /v1/... or a custom header.
  • Return consistent envelopes for lists: { data: [...], meta: {...} }.
  • Use kebab-case for multi-word paths: /order-items, not /orderItems.

โŒ Don't

  • Put verbs in the URL: /deleteUser/42 โ†’ use DELETE /users/42.
  • Return 200 OK with an error message inside the body.
  • Expose raw database IDs or internal table names.
  • Break existing clients โ€” add fields, don't rename or remove them without a new version.
  • Nest more than two levels deep: /users/1/orders/2/items/3/reviews is a code smell.

Pagination, filtering, sorting

# Offset pagination (simple, good for small datasets)
GET /v1/products?page=3&limit=20

# Cursor pagination (stable & fast for large datasets)
GET /v1/products?limit=20&cursor=eyJpZCI6MTA4N30

# Filtering + sorting (minus = descending)
GET /v1/products?category=laptops&minPrice=500&sort=-createdAt

# Sparse fieldsets (return only what you need)
GET /v1/products?fields=id,name,price
{
  "data": [ /* 20 items */ ],
  "meta": {
    "page": 3,
    "limit": 20,
    "total": 412,
    "nextCursor": "eyJpZCI6MTEwN30"
  }
}

API Design Maturity โ€” the Richardson Maturity Model

LevelNameWhat it adds
0The Swamp of POXOne endpoint, one method (like XML-RPC over POST).
1ResourcesDistinct URLs per resource.
2HTTP VerbsUses GET/POST/PUT/DELETE correctly + status codes. Most APIs live here.
3Hypermedia (HATEOAS)Responses include links to related actions. Rare in practice.

09 How to Connect to an API

Consuming an API follows the same loop in every language: build a request โ†’ send it โ†’ check the status โ†’ parse the body โ†’ handle errors.

JavaScript โ€” fetch (built into browsers & Node 18+)

async function createBook() {
  const response = await fetch('https://api.example.com/v1/books', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${process.env.API_TOKEN}`
    },
    body: JSON.stringify({ title: 'Clean Code', author: 'Robert Martin' })
  });

  // fetch does NOT throw on 4xx/5xx โ€” check manually
  if (!response.ok) {
    const detail = await response.text();
    throw new Error(`HTTP ${response.status}: ${detail}`);
  }

  return response.json();
}

JavaScript โ€” axios (popular library)

import axios from 'axios';

const api = axios.create({
  baseURL: 'https://api.example.com/v1',
  timeout: 10000,
  headers: { Authorization: `Bearer ${token}` }
});

try {
  const { data } = await api.get('/books', { params: { page: 1, limit: 20 } });
  console.log(data);
} catch (err) {
  if (err.response)  console.error('Server said:', err.response.status);
  else if (err.request) console.error('No response received');
  else                 console.error('Setup error:', err.message);
}

Python โ€” requests

import requests

response = requests.post(
    "https://api.example.com/v1/books",
    headers={"Authorization": f"Bearer {TOKEN}"},
    json={"title": "Clean Code", "author": "Robert Martin"},
    timeout=10,
)

response.raise_for_status()   # throws on 4xx/5xx
book = response.json()
print(book["id"])

cURL โ€” the universal debugging tool

# GET with auth header
curl https://api.example.com/v1/books \
  -H "Authorization: Bearer $TOKEN"

# POST with a JSON body (-i shows response headers)
curl -i -X POST https://api.example.com/v1/books \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"title":"Clean Code","author":"Robert Martin"}'

GraphQL โ€” one endpoint, exact fields

query {
  user(id: "42") {
    name
    email
    orders(last: 3) {
      id
      total
    }
  }
}
const res = await fetch('https://api.example.com/graphql', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
  body: JSON.stringify({ query, variables: { id: '42' } })
});

Handling rate limits gracefully

// Respect 429 and the Retry-After header
async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const res = await fetch(url, options);

    if (res.status !== 429 && res.status < 500) return res;

    const wait = Number(res.headers.get('Retry-After')) * 1000
               || 2 ** attempt * 500;   // exponential backoff

    await new Promise(r => setTimeout(r, wait));
  }
  throw new Error('Max retries exceeded');
}
CORS

Browsers block cross-origin requests unless the server sends Access-Control-Allow-Origin. CORS is a browser rule โ€” server-to-server calls (cURL, Python, Node) are unaffected. You must fix CORS on the server, not the client.

10 REST vs GraphQL vs SOAP vs gRPC

Feature REST GraphQL SOAP gRPC
FormatJSON (usually)JSONXMLProtobuf (binary)
TransportHTTP/1.1, HTTP/2HTTPHTTP, SMTP, TCPHTTP/2
EndpointsManyOneManyMany
TypingLooseStrong (schema)Very strong (WSDL)Very strong (.proto)
Over/under-fetchingCommon problemSolvedVerboseEfficient
CachingExcellent (HTTP)ManualPoorLimited
Browser supportNativeNativePoorNeeds grpc-web
StreamingLimitedSubscriptionsNoExcellent (bidirectional)
Best forPublic APIs, CRUDComplex UIs, mobileEnterprise, legacyInternal microservices
Not mutually exclusive

Real systems mix these. It's completely normal to have a public REST API, gRPC between internal services, and GraphQL for the mobile client.

11 API Versioning

Every API changes. Versioning is how you evolve without breaking existing clients.

Four common strategies

StrategyExampleProsCons
URI Path GET /v1/books Obvious, easy to route, cache-friendly Pollutes URLs; "v1" isn't a real resource
Query param GET /books?version=1 Simple to add Easy to forget; hurts caching
Custom header X-API-Version: 1 Clean URLs Invisible in a browser address bar
Content negotiation Accept: application/vnd.shop.v1+json RESTful "correct" approach Verbose; hard to test manually

Breaking vs non-breaking changes

โœ… Safe (non-breaking)

Adding a new endpoint, adding an optional request field, adding a field to a response, adding a new enum value that clients can ignore.

โŒ Breaking

Renaming or removing fields, changing a type (string โ†’ number), making an optional field required, changing URL structure, changing error codes.

Deprecation done right

Deprecation: Sat, 01 Mar 2025 00:00:00 GMT
Sunset: Tue, 01 Jul 2025 00:00:00 GMT
Link: <https://api.example.com/v2/books>; rel="successor-version"
  • Announce the change in a changelog and email list months ahead.
  • Log which clients still hit the old version so you can reach out.
  • Run both versions in parallel for a deprecation window.
  • Return the Sunset header so clients know the deadline programmatically.
Semantic versioning for APIs

Use MAJOR.MINOR.PATCH โ€” bump MAJOR for breaking changes, MINOR for backward-compatible additions, PATCH for bug fixes. Most public APIs expose only the MAJOR number in the URL.

12 API Security Deep Dive

APIs are a top attack target because they often expose business logic and data directly. Here is what to defend against.

OWASP API Security Top 10 (2023)

#RiskIn plain English
API1Broken Object Level Authorization (BOLA)User A can read User B's data by changing an ID in the URL. The #1 API risk.
API2Broken AuthenticationWeak login, no token expiry, predictable reset codes.
API3Broken Object Property Level AuthorizationToo much data returned, or fields the client shouldn't be able to set (e.g. isAdmin).
API4Unrestricted Resource ConsumptionNo rate limits or pagination caps โ†’ DoS or huge bills.
API5Broken Function Level AuthorizationA normal user can call admin endpoints.
API6Unrestricted Access to Sensitive Business FlowsScalping, spam, or abuse via automated legitimate calls.
API7Server-Side Request Forgery (SSRF)Attacker makes your server fetch internal URLs (e.g. cloud metadata).
API8Security MisconfigurationDebug mode in prod, permissive CORS, verbose errors.
API9Improper Inventory ManagementForgotten old API versions still exposed.
API10Unsafe Consumption of APIsTrusting third-party API data without validation.

Rate-limiting algorithms

Fixed Window

Count requests per fixed time bucket (e.g. 100/min). Simple but allows bursts at edges.

Sliding Window

Smoother than fixed window โ€” counts requests over the last N seconds continuously.

Token Bucket

Bucket refills tokens at a steady rate; each request takes one. Allows controlled bursts.

Leaky Bucket

Requests "leak" out at a constant rate. Smooths traffic, no bursts allowed.

Standard rate-limit headers

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 42
X-RateLimit-Reset: 1705316400
Retry-After: 30

Essential security headers

Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Security-Policy: default-src 'self'
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Cache-Control: no-store   # for sensitive responses
Golden rules
  • Authorize every request โ€” never rely on the client to hide data.
  • Validate and sanitize every input, including headers and query params.
  • Use parameterized queries to stop injection.
  • Rotate secrets regularly and store them in a secrets manager, not in code.
  • Log security events โ€” but redact tokens, passwords, and PII.
  • Test with a security scanner (OWASP ZAP, Burp Suite) before shipping.

13 Architecture Patterns

How APIs are arranged in real systems โ€” the shapes you'll see in job interviews and production diagrams.

๐Ÿข Monolith

One deployable app. Simple to start; all code talks in-process. Works fine for most teams.

๐Ÿงฉ Microservices

Many small services, each owning its data. Communicate via APIs (REST, gRPC) or events.

๐Ÿšช API Gateway

Single front door: routing, auth, rate limits, logging, versioning. Often Kong, NGINX, AWS API Gateway.

๐ŸŽจ BFF (Backend for Frontend)

One tailored API per client (web, iOS, Android) sitting in front of shared services.

๐Ÿ•ธ๏ธ Service Mesh

Sidecar proxies (Istio, Linkerd) handle mTLS, retries, and telemetry between services.

๐Ÿ“จ Event-Driven

Services publish events to a broker (Kafka, RabbitMQ, SNS). Great for async workflows.

โ˜๏ธ Serverless APIs

Each endpoint is a function (AWS Lambda, Cloudflare Workers). Pay-per-invocation, auto-scaling.

๐Ÿงฑ API Composition

A layer that fans out to several APIs and merges results โ€” common in mobile backends.

Typical layered request path

ClientBrowser / mobile
โ†’
CDN / WAFCache & filter
โ†’
API GatewayAuth, rate limit
โ†’
ServiceBusiness logic
โ†’
DatabasePersist data

Microservice communication: sync vs async

StyleHowWhen to use
SynchronousREST or gRPC call, client waits for replyNeed an immediate answer (e.g. fetch user profile).
AsynchronousPublish event to a queue or topicLong tasks, fan-out, decoupling (e.g. send email after order).
Resilience patterns

In distributed systems, add timeouts, retries with backoff, circuit breakers (stop calling a failing service), bulkheads (isolate failures), and idempotency keys so retries don't duplicate side effects.

14 Caching & Performance

Caching is the single highest-leverage way to make an API fast and cheap. HTTP has caching built in โ€” use it.

Key caching headers

HeaderWhat it doesExample
Cache-ControlWho may cache and for how longpublic, max-age=3600
ETagFingerprint of the response body"33a64df5"
Last-ModifiedWhen the resource last changedWed, 15 Jan 2025 10:00:00 GMT
VaryWhich request headers affect the responseAccept, Accept-Encoding
ExpiresLegacy absolute expiry timeWed, 15 Jan 2025 11:00:00 GMT

Conditional requests โ€” saving bandwidth

# First request: server responds with an ETag
GET /v1/products/42
ETag: "33a64df5"

# Next request: client sends the ETag back
GET /v1/products/42
If-None-Match: "33a64df5"

# If unchanged, server replies with a tiny 304 and no body
HTTP/1.1 304 Not Modified

Cache-Control directives worth knowing

  • public โ€” any cache (including CDNs) may store it.
  • private โ€” only the end user's browser may cache it.
  • no-store โ€” never cache (use for sensitive data).
  • no-cache โ€” may store, but must revalidate before each use.
  • max-age=600 โ€” fresh for 600 seconds.
  • stale-while-revalidate=60 โ€” serve stale for 60s while refreshing in the background.

Other performance wins

๐Ÿ—œ๏ธ Compression

Enable gzip or brotli. JSON compresses 70โ€“90%. Always send Accept-Encoding.

๐Ÿ”Œ Connection reuse

HTTP keep-alive and connection pools avoid TCP + TLS handshakes per request.

๐Ÿ“„ Pagination

Never return unbounded lists. Cap limit server-side (e.g. max 100).

๐Ÿงฎ Avoid N+1 queries

One query per item in a loop is the classic API performance killer. Batch or join.

๐ŸŒ CDN

Put a CDN in front of cacheable GETs to serve users from an edge near them.

๐Ÿ“ฆ Partial responses

Let clients request only the fields they need (?fields= or GraphQL).

15 Real-time APIs

Sometimes the server needs to tell the client something now, instead of waiting to be asked. Four main patterns exist.

PatternDirectionLatencyBest for
Short pollingClient โ†’ server, repeatedlyHigh (interval-bound)Simple dashboards, low-frequency updates
Long pollingClient โ†’ server, held openMediumLegacy real-time when WebSockets aren't available
Server-Sent Events (SSE)Server โ†’ client, one-wayLowLive feeds, notifications, progress bars
WebSocketsBidirectionalLowestChat, multiplayer, collaborative editing
WebhooksServer โ†’ server, event-drivenLowPayments, CI/CD, third-party integrations

WebSocket โ€” minimal example

// Browser side
const ws = new WebSocket('wss://api.example.com/ws');

ws.addEventListener('open',    () => ws.send(JSON.stringify({ type: 'subscribe', room: 'prices' })));
ws.addEventListener('message', e => console.log('Update:', JSON.parse(e.data)));
ws.addEventListener('close',   () => console.log('Disconnected'));

Server-Sent Events โ€” simpler, one-way

// Browser side
const es = new EventSource('/api/notifications/stream');

es.onmessage = e => console.log('Notification:', e.data);
es.onerror   = () => console.log('Stream lost, retryingโ€ฆ');

Webhook โ€” the server calls you

// Express receiver for a Stripe-style webhook
app.post('/webhooks/payment', express.raw({ type: '*/*' }), (req, res) => {
  const signature = req.headers['stripe-signature'];

  let event;
  try {
    event = stripe.webhooks.constructEvent(
      req.body, signature, process.env.WEBHOOK_SECRET
    );
  } catch (err) {
    return res.status(400).send(`Webhook Error: ${err.message}`);
  }

  if (event.type === 'payment_intent.succeeded') {
    // handle the eventโ€ฆ
  }

  res.json({ received: true });   // respond fast
});
Webhook best practices
  • Verify the signature โ€” never trust an unauthenticated webhook.
  • Respond 2xx quickly โ€” do heavy work asynchronously.
  • Be idempotent โ€” the same event may be delivered more than once.
  • Use HTTPS and an allowlist of source IPs if possible.

16 Documentation & Developer Experience

A great API with bad docs is a bad API. DX (developer experience) is a feature.

๐Ÿ“˜ OpenAPI / Swagger

Machine-readable spec. Generates docs, SDKs, mocks, and tests. The industry standard for REST.

๐Ÿ“— GraphQL SDL

The schema is the documentation. Tools like GraphiQL give an interactive explorer.

๐Ÿ“™ Postman Collections

Runnable examples your users can import and try in one click.

๐Ÿš€ Quickstart

A 5-minute "hello world" โ€” copy, paste, run. If it takes longer, users bounce.

๐Ÿงช Sandbox environment

Fake data, no real charges. Lets developers experiment safely.

๐Ÿ“ฆ Client SDKs

Official libraries in JS, Python, Go, etc. Reduce time-to-first-call dramatically.

๐Ÿ“ Changelog

Dated list of changes, marked as breaking / added / fixed. Subscribe-able.

๐ŸŒ Developer portal

One place for docs, keys, status page, support, and terms.

What a great doc page contains

  • Authentication โ€” how to get and use a key or token.
  • Base URL and environments (sandbox vs production).
  • Every endpoint with method, path, params, sample request, sample response.
  • Error reference โ€” every code and what it means.
  • Rate limits โ€” the numbers and the headers.
  • Pagination โ€” how it works and where to find the next page.
  • Webhooks โ€” events, payloads, signature verification.
  • Changelog & deprecation policy.

OpenAPI snippet

openapi: 3.0.3
info:
  title: Books API
  version: 1.0.0
paths:
  /books:
    get:
      summary: List all books
      responses:
        '200':
          description: A list of books
          content:
            application/json:
              schema:
                type: array
                items: { $ref: '#/components/schemas/Book' }
DX rule of thumb

If a new developer can't make a successful API call in under 10 minutes with only your docs, your onboarding is broken.

17 Testing & Monitoring

Untested APIs break silently. Unmonitored APIs break loudly at 3 a.m.

Testing layers

LayerWhat it checksTools
UnitOne handler or function in isolationJest, Pytest, Go test
IntegrationEndpoint + database + auth working togetherSupertest, Testcontainers
ContractThe API still matches the agreed schemaPact, Dredd, Schemathesis
End-to-endThe full user journey across servicesCypress, Playwright, Postman
LoadBehaviour under high traffick6, JMeter, Artillery, Locust
SecurityCommon vulnerabilitiesOWASP ZAP, Burp Suite

Monitoring: the four golden signals

โฑ๏ธ Latency

How long requests take. Track p50, p95, p99 โ€” averages hide pain.

๐Ÿšฆ Traffic

Requests per second, by endpoint and by client.

โŒ Errors

Rate of 5xx and 4xx responses. Alert on spikes, not just totals.

๐Ÿ’ง Saturation

How full are your resources? CPU, memory, DB connections, queue depth.

Observability: the three pillars

  • Logs โ€” structured JSON events with a request ID so you can trace a single call.
  • Metrics โ€” numeric time series for dashboards and alerting.
  • Traces โ€” a single request's journey across services (OpenTelemetry, Jaeger, Tempo).

SLI, SLO, SLA โ€” what's the difference?

TermMeaningExample
SLIIndicator โ€” a number you measurep99 latency is 240 ms
SLOObjective โ€” an internal target99.9% of requests under 500 ms
SLAAgreement โ€” a contract with customers, often with penalties99.95% uptime or credits

Distributed tracing โ€” propag

# Trace context propagates via headers
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
X-Request-ID: req_8f2a91c
Always return a request ID

Give every response a unique X-Request-ID and include it in logs. When a customer reports a bug, they can paste the ID and you can find the exact trace in seconds.

18 Best Practices Checklist

๐Ÿ”’ Always HTTPS

Never transmit tokens or data over plain HTTP. Enforce TLS and use HSTS.

๐Ÿ“„ Document everything

Use OpenAPI/Swagger. Include examples for every endpoint and every error.

๐Ÿงฑ Validate all input

Type, length, range, format. Reject early with a clear 400 and field-level detail.

๐Ÿšฆ Rate limit

Protect your backend. Return 429 with Retry-After and X-RateLimit-* headers.

๐Ÿ”ข Version from day one

/v1/ in the path or a custom media type. Never break existing clients.

๐Ÿ“Š Log & monitor

Track latency (p50/p95/p99), error rate, and throughput. Add a request ID to every response.

โšก Cache smartly

Send ETag, Cache-Control, and support conditional requests with 304.

๐Ÿงช Test automatically

Unit tests for handlers, integration tests for endpoints, contract tests against the schema.

โ™ป๏ธ Idempotency keys

For payment-like POSTs, let clients send an Idempotency-Key to prevent duplicates.

๐ŸŒ CORS & security headers

Set Content-Security-Policy, X-Content-Type-Options, and a strict origin allowlist.

๐Ÿ“‰ Paginate everything

Cap limit server-side. Never let a client pull an unbounded table.

๐Ÿ“ฃ Publish a changelog

Announce changes early. Mark breaking ones clearly. Give clients time to migrate.

Security quick wins

  • Least privilege: scopes and roles should grant the minimum needed.
  • Short-lived tokens: access tokens expire in minutes; refresh tokens rotate.
  • Never log secrets: redact Authorization headers from logs.
  • Prevent injection: always use parameterized queries for the database.
  • Limit payload size: cap request bodies to avoid memory exhaustion.
  • Use a gateway: centralize auth, throttling, and TLS termination.

19 Tools & Ecosystem

ToolPurpose
PostmanGUI client for building, testing, and sharing API requests
InsomniaLightweight REST/GraphQL client
BrunoOffline, Git-friendly API client
Swagger / OpenAPISpecification format + interactive documentation UI
StoplightVisual API design, mocking, and documentation platform
httpieHuman-friendly command-line HTTP client
curlUniversal CLI tool โ€” available everywhere
Jest / Pytest / SupertestAutomated endpoint testing
PactConsumer-driven contract testing
k6 / Artillery / JMeterLoad and performance testing
OWASP ZAP / Burp SuiteSecurity scanning
ngrok / localtunnelExpose your local API to the internet for webhook testing
Kong / NGINX / AWS API GatewayAPI gateways: routing, auth, rate limiting
OpenTelemetry / JaegerDistributed tracing and observability
RedisCache, rate-limit counters, session store
Kafka / RabbitMQ / SNS+SQSEvent-driven messaging between services

Popular frameworks for building APIs

LanguageFrameworkNotes
JavaScript / TypeScriptExpress, Fastify, NestJS, HonoHuge ecosystem; Fastify and Hono are very fast
PythonFastAPI, Flask, Django REST FrameworkFastAPI gives OpenAPI docs for free
GoGin, Fiber, Echo, ChiExcellent performance and concurrency
Java / KotlinSpring Boot, Ktor, MicronautEnterprise favourite; Spring has everything
RubyRails API, SinatraRapid development, convention over configuration
C# / .NETASP.NET CoreHigh performance, strong tooling
RustAxum, Actix Web, RocketMaximum performance and safety
PHPLaravel, SymfonyStill powers a huge share of the web

20 Technical Glossary

Core API vocabulary in plain language.

TermMeaning
EndpointA specific URL path that accepts requests, e.g. /v1/users
ResourceThe "thing" an endpoint represents โ€” a user, an order, a book
PayloadThe data carried in a request or response body
HeaderKeyโ€“value metadata sent with a request or response
Query stringThe ?key=value&โ€ฆ portion of a URL used for filters and options
Path parameterA variable inside the URL path, e.g. /users/:id
IdempotentRepeating the call produces the same result as calling once
Idempotency keyA unique client-supplied value that lets the server deduplicate retried writes
StatelessThe server keeps no session state between requests; every call is self-contained
StatefulThe server remembers things between calls (e.g. a WebSocket session)
SerializationTurning an object into a transmittable format like JSON or XML
DeserializationTurning received data back into an object your code can use
MarshallingAnother word for serialization, common in Java/Go ecosystems
Rate limitingRestricting how many requests a client may make per time window
ThrottlingSlowing down requests rather than rejecting them outright
QuotaA long-term usage allowance (e.g. 10 000 calls per month)
WebhookA user-defined HTTP callback triggered by an event on the provider side
PollingRepeatedly asking the server for updates; the alternative to webhooks
Long pollingThe server holds the request open until there's something to return
API GatewayA layer in front of services handling auth, routing, and rate limits
Reverse proxyA server that sits in front of your app, forwarding and possibly caching requests
SDKA language-specific library that wraps an API for convenience
ContractThe agreed request/response schema between client and server
SchemaA formal definition of what data is allowed and its types
OpenAPIA standard, machine-readable description format for REST APIs
Swagger UIThe interactive web page that renders an OpenAPI spec
Mock serverA fake API that returns sample responses, used before the real one exists
SandboxA safe test environment with fake data and no real side effects
Bearer tokenA credential sent in the Authorization header; whoever holds it is granted access
Access tokenShort-lived credential that proves you're authorized to call an API
Refresh tokenLong-lived credential used to get new access tokens without re-login
ScopeA named permission granted to a token, e.g. read:orders
ClaimA piece of information inside a JWT, like sub (subject) or exp (expiry)
CORSBrowser security rule governing cross-origin requests
PreflightAn automatic OPTIONS request the browser sends before a cross-origin call
ETagA fingerprint of a response used for cache validation
Conditional requestA request that includes validators (If-None-Match) so the server can return 304
Cache invalidationRemoving or refreshing stale cached data โ€” famously hard
TTLTime To Live โ€” how long a cached item or token stays valid
CDNContent Delivery Network โ€” edge servers that cache and serve content near users
Circuit breakerA pattern that stops calling a failing service to prevent cascading failures
BackpressureSignalling upstream to slow down because you're overwhelmed
Retry with backoffRetrying a failed call, waiting longer each time to avoid hammering the server
Fan-outSending one request/event to many downstream consumers
BFFBackend For Frontend โ€” a tailored API layer per client type
SidecarA helper process running alongside a service (common in service meshes)
Service meshInfrastructure layer that manages service-to-service traffic (Istio, Linkerd)
HATEOASHypermedia As The Engine Of Application State โ€” responses include links to next actions
Over-fetchingReceiving more data than you need (common in REST)
Under-fetchingNeeding multiple calls to assemble one screen (also common in REST)
ResolverIn GraphQL, the function that fetches data for one field
MutationIn GraphQL, an operation that changes data (like POST/PUT/DELETE)
SubscriptionIn GraphQL, a long-lived operation that pushes updates over a socket
BatchingCombining many small calls into one to reduce overhead
N+1 problemMaking one query per item in a list, tanking performance
PaginationSplitting large result sets into pages
CursorAn opaque pointer to "where you are" in a paginated list
EnvelopeA wrapper object around data, e.g. { data, meta, error }
Payload size limitA cap on how large a request body may be
Request IDA unique ID per request, used to correlate logs and traces
Correlation IDAn ID shared across a chain of calls across services
Health checkAn endpoint (often /health) that reports if the service is alive
Readiness probeSignals a service is ready to receive traffic
Liveness probeSignals a service is still running and should not be restarted
Blue/green deployRunning two identical environments, switching traffic between them
Canary releaseRolling out a change to a small percentage of users first
Feature flagA runtime switch to turn behaviour on/off without redeploying
Backward compatibleOld clients keep working after the change
DeprecationMarking something as obsolete but still supported for a transition period
SunsetThe date after which a deprecated thing stops working

21 Acronyms & Idioms for Beginners

Every field has its own language. Here is the API world's โ€” explained without jargon.

A. Acronyms you'll see everywhere

API Application Programming Interface

A contract that lets two programs talk to each other.

REST Representational State Transfer

An architectural style for web APIs built on resources and HTTP verbs.

HTTP HyperText Transfer Protocol

The language browsers and servers speak. Almost every API rides on it.

HTTPS HTTP Secure

HTTP encrypted with TLS. Always use this in production.

TLS / SSL Transport Layer Security / Secure Sockets Layer

The encryption layer behind HTTPS. SSL is the older name; TLS is what's used today.

JSON JavaScript Object Notation

Lightweight text format for data. The default for modern APIs.

XML eXtensible Markup Language

Older, verbose markup format. Still used by SOAP and some enterprise systems.

YAML YAML Ain't Markup Language

Human-friendly data format, common for config files and OpenAPI specs.

URL Uniform Resource Locator

The full web address, e.g. https://api.example.com/v1/books.

URI / URN Uniform Resource Identifier / Name

Umbrella terms: a URI identifies a resource; a URN names it without saying how to find it.

CRUD Create, Read, Update, Delete

The four basic operations on data. Maps to POST, GET, PUT/PATCH, DELETE.

SDK Software Development Kit

A language-specific library that wraps an API so you don't hand-craft HTTP calls.

CLI Command-Line Interface

A text-based tool you run in a terminal, like curl.

GUI Graphical User Interface

A visual app with buttons and windows โ€” like Postman.

JWT JSON Web Token

A signed, self-contained token used for stateless authentication.

OAuth Open Authorization

A standard for granting apps access to your data without sharing your password.

OIDC OpenID Connect

OAuth 2.0 plus an identity layer โ€” the "Sign in withโ€ฆ" standard.

SSO Single Sign-On

Log in once, access many systems.

MFA / 2FA Multi-Factor Authentication / Two-Factor Authentication

Requiring more than a password โ€” an SMS code, an authenticator app, a hardware key.

mTLS Mutual TLS

Both client and server present certificates. Common inside zero-trust networks.

CORS Cross-Origin Resource Sharing

A browser rule that decides whether a page can call an API on a different domain.

CSRF Cross-Site Request Forgery

Tricking a logged-in browser into making an unwanted request. Prevented with tokens and SameSite cookies.

XSS Cross-Site Scripting

Injecting malicious scripts into a page. Prevented by escaping output and CSP headers.

SQLi SQL Injection

Sneaking SQL through unvalidated input. Prevented with parameterized queries.

SSRF Server-Side Request Forgery

Making a server fetch an internal URL on the attacker's behalf.

BOLA Broken Object Level Authorization

The #1 API security risk: users can access objects they don't own by changing an ID.

OWASP Open Worldwide Application Security Project

A nonprofit that publishes the famous Top 10 security risk lists.

WAF Web Application Firewall

A filter that blocks common attacks before they reach your app.

DDoS Distributed Denial of Service

Flooding a service with traffic from many sources to knock it offline.

SOAP Simple Object Access Protocol

A strict, XML-based protocol for enterprise APIs. Uses WSDL to describe itself.

WSDL Web Services Description Language

The XML contract that describes a SOAP service.

gRPC Google Remote Procedure Call

A high-performance binary RPC framework using HTTP/2 and Protocol Buffers.

RPC Remote Procedure Call

Calling a function on another machine as if it were local.

SSE Server-Sent Events

A one-way stream from server to browser over plain HTTP.

WS WebSocket

A persistent, two-way connection between client and server.

BFF Backend For Frontend

A tailored API layer for one specific client type.

CDN Content Delivery Network

Edge servers around the world that cache and serve content near your users.

TTL Time To Live

How long a cached item or token remains valid.

ID / UUID Identifier / Universally Unique Identifier

A value that uniquely identifies something. UUIDs look like f81d4fae-7dec-11d0-a765-00a0c91e6bf6.

PII Personally Identifiable Information

Data that can identify a person โ€” names, emails, SSNs. Handle with care and never log it raw.

GDPR General Data Protection Regulation

EU privacy law. Affects how APIs store, expose, and delete personal data.

SLA / SLO / SLI Service Level Agreement / Objective / Indicator

The customer contract / the internal target / the number you measure.

CI/CD Continuous Integration / Continuous Delivery

Automatically testing and deploying every code change.

DX Developer Experience

How pleasant your API is to use โ€” docs, SDKs, errors, sandbox.

UX User Experience

How pleasant your product is for end users.

ORM Object-Relational Mapper

A library that lets you talk to a database with objects instead of raw SQL (e.g. Prisma, SQLAlchemy).

DB / RDBMS / NoSQL Database / Relational DBMS / Not-Only-SQL

Where data lives. Relational uses tables and joins; NoSQL uses documents, key-value, or graphs.

FIFO / LIFO First-In-First-Out / Last-In-First-Out

Queue order. Most message queues are FIFO; stacks are LIFO.

E2E End-to-End

A test that exercises the full flow from user to database and back.

p50 / p95 / p99 Percentile latencies

"95% of requests are faster than X." More useful than averages for spotting pain.

B. Idioms & phrases you'll hear on day one

PhraseWhat it really means
"Hit the endpoint"Send an HTTP request to that URL.
"Stand up an API"Build and deploy an API so it's running.
"Spin up a server"Start a new server instance.
"Round trip"One full request-and-response cycle. Fewer round trips = faster app.
"Chatty API"An API that forces many small calls to do one job. Usually a design smell.
"Over-fetching"Getting more data back than you'll use. Wastes bandwidth.
"Under-fetching"Needing several calls to assemble one screen. GraphQL was invented to fix this.
"N+1 problem"One query per item in a list. The classic performance killer.
"Thundering herd"Thousands of clients retrying at once and crushing the server.
"Retry storm"Same idea โ€” uncontrolled retries making an outage worse.
"Back-of-the-envelope"A rough estimate, not a precise measurement.
"Happy path"The scenario where everything works. Always test the unhappy paths too.
"Edge case"An unusual input that breaks naรฏve code โ€” empty lists, huge numbers, weird Unicode.
"Bikeshedding"Arguing about trivia (like naming) while ignoring the hard problems.
"Boil the ocean"Try to do everything at once instead of shipping something small.
"Dogfooding"Using your own API internally before releasing it. Best way to find pain points.
"Eating your own dog food"The full version of the above.
"Greenfield"A brand-new project with no legacy constraints.
"Brownfield"Adding to an existing, messy system. Most real work is brownfield.
"Legacy code"Code that works but is scary to touch. Often the reason SOAP still exists.
"Technical debt"Shortcuts taken now that will cost more to fix later.
"Yak shaving"A chain of small tasks that distracts from the original goal.
"Rubber duck debugging"Explaining your problem out loud until you spot the bug yourself.
"Works on my machine"The classic excuse when something only fails in production.
"Ship it"Deploy it. Often said with a mix of hope and fatalism.
"Bake in the oven"Run a new change in a test environment for a while before full rollout.
"Break glass"An emergency override to bypass normal controls.
"Blast radius"How much breaks if a change goes wrong. Keep it small.
"Graceful degradation"When one part fails, the rest still works โ€” just with less functionality.
"Fail fast"Return an error immediately rather than waiting or guessing.
"Fail closed"On error, deny access. The safe default for security.
"Fail open"On error, allow access. Almost always the wrong choice for auth.
"Source of truth"The authoritative place where a piece of data lives.
"Single source of truth"One place โ€” never two โ€” that owns a piece of data.
"Idempotent operation"Doing it twice is the same as doing it once.
"Contract-first"Write the API spec before writing code.
"Code-first"Write the code, then generate the spec from it.
"Wrapping an API"Building a layer around someone else's API to simplify or normalize it.
"Shimming"A thin adapter that makes two incompatible things work together.
"Glue code"Code whose only job is connecting other pieces together.
"Vendor lock-in"Being so dependent on one provider that switching is painful.
"Feature creep"Slowly adding more scope than anyone agreed to.
"Scope creep"Same idea, but for the project as a whole.
"MVP"Minimum Viable Product โ€” the smallest thing that delivers value.
"POC"Proof of Concept โ€” a quick experiment to see if an idea works.
"Spike"A short, time-boxed investigation to reduce uncertainty.
"Smoke test"A quick check that the basics still work after a change.
"Synthetic monitoring"Bots that call your API on a schedule to detect outages before users do.
"Golden path"The recommended, well-supported way to do something. Also called the "paved road".
"Paved road"The supported tooling and patterns teams should default to.
"Off the paved road"Doing something custom and unsupported โ€” allowed, but you own the consequences.
"Postman-driven development"Half-joking: building an API by clicking around Postman instead of writing proper tests.
"Fire and forget"Send a request or event without waiting for the result.
"At-least-once delivery"A message may arrive more than once โ€” so your handler must be idempotent.
"At-most-once delivery"A message may be lost but never duplicated.
"Exactly-once delivery"The holy grail โ€” very hard to truly achieve; usually simulated with idempotency.
"Eventually consistent"Data will match across systemsโ€ฆ eventually. Not instantly.
"Strongly consistent"Every read sees the latest write. Slower but simpler to reason about.
You're ready

If you understand the sections above and the two glossaries, you can read almost any API documentation, hold your own in a design discussion, and build or consume a real API. The rest is practice.

← Back APIs — The Complete Guide ⌂ Encyclopedia Next →