🔗 API Design
APIs & REST Complete Cheatsheet
REST principles, HTTP methods, auth, design patterns, GraphQL comparison and OpenAPI.
01
REST Principles
▼
REST
Representational State Transfer. Architectural style for web APIs. Stateless, client-server.
Resource
Everything is a resource (noun): users, products, orders, not verbs.
Stateless
Each request contains all info needed. Server stores NO session state.
Uniform Interface
Consistent API design. Resources identified by URL. Standard methods.
HATEOAS
Hypermedia as Engine of Application State. Responses include links to next actions.
Idempotent
Same request = same result. GET, PUT, DELETE are idempotent. POST is NOT.
Safe methods
No side effects. GET, HEAD, OPTIONS are safe. POST, PUT, DELETE are not.
Content negotiation
Client specifies format: Accept: application/json. Server responds accordingly.
RESTResource naming convention
# Good — nouns, plural, lowercase, hyphens GET /users # list all users GET /users/123 # get user 123 POST /users # create user PUT /users/123 # replace user 123 (full) PATCH /users/123 # partial update user 123 DELETE /users/123 # delete user 123 GET /users/123/orders # user's orders (nested) GET /users/123/orders/456 # specific order of user # Bad — verbs in URL, inconsistent naming GET /getUser?id=123 ❌ POST /createUser ❌ GET /user ❌ (should be plural /users) GET /Users ❌ (should be lowercase)
02
HTTP Methods & Status
▼
| Method | Operation | Idempotent | Safe | Body |
|---|---|---|---|---|
| GET | Read | ✅ Yes | ✅ Yes | No |
| POST | Create | ❌ No | ❌ No | Yes |
| PUT | Replace | ✅ Yes | ❌ No | Yes |
| PATCH | Partial update | ❌ Usually | ❌ No | Yes |
| DELETE | Delete | ✅ Yes | ❌ No | Optional |
| HEAD | Like GET, no body | ✅ Yes | ✅ Yes | No |
| OPTIONS | List allowed methods | ✅ Yes | ✅ Yes | No |
RESTHTTP status codes
1xx Informational 100 Continue 2xx Success 200 OK — GET success 201 Created — POST success (return new resource) 204 No Content — DELETE success (no body) 206 Partial Content — Range request (file download) 3xx Redirection 301 Moved Permanently — Update bookmarks 302 Found — Temporary redirect 304 Not Modified — Use cache (ETag match) 4xx Client Error 400 Bad Request — Invalid syntax, missing field 401 Unauthorized — Not authenticated (login first) 403 Forbidden — Authenticated but not allowed 404 Not Found — Resource doesn't exist 409 Conflict — Duplicate resource 422 Unprocessable — Valid syntax but semantic errors 429 Too Many Requests — Rate limit exceeded 5xx Server Error 500 Internal Server Error — Unexpected server error 502 Bad Gateway — Upstream server error 503 Service Unavailable — Server down, maintenance
03
Request & Response
▼
RESTRequest and Response format
# Request
POST /api/v1/users HTTP/1.1
Host: api.bitwithbite.com
Content-Type: application/json
Authorization: Bearer eyJhbGc...
Accept: application/json
X-Request-ID: abc123
{
"name": "Ali Khan",
"email": "ali@test.com",
"role": "student"
}
# Response (201 Created)
HTTP/1.1 201 Created
Content-Type: application/json
Location: /api/v1/users/456
{
"success": true,
"data": {
"id": 456,
"name": "Ali Khan",
"email": "ali@test.com",
"createdAt": "2026-04-19T10:00:00Z"
}
}
# Error response (422)
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid email format",
"details": [{"field": "email", "message": "Must be valid email"}]
}
}
04
Authentication
▼
RESTAuthentication methods
# 1. API Key (simplest)
GET /api/data
Authorization: ApiKey your-api-key-here
# OR in header: X-API-Key: your-key
# 2. Basic Auth (username:password base64)
Authorization: Basic dXNlcjpwYXNzd29yZA==
# Decoded: user:password
# 3. Bearer Token / JWT (most common)
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
# JWT structure: header.payload.signature
# header: {alg, typ}
# payload: {sub, name, role, exp, iat}
# signature: HMAC_SHA256(header+payload, secret)
# 4. OAuth 2.0 (delegated auth)
# Client requests token from Auth Server
# Grants: Authorization Code, Client Credentials, PKCE
# JWT in Node.js
const jwt = require('jsonwebtoken');
const token = jwt.sign({userId: 123, role: 'admin'}, SECRET, {expiresIn: '7d'});
const decoded = jwt.verify(token, SECRET);
Refresh tokens
Long-lived token to get new access token. Store securely.
Token expiry
Short-lived access tokens (15min-1hr). Reduces exposure if stolen.
PKCE
Proof Key for Code Exchange. Secure OAuth for SPAs/mobile apps.
05
API Design Best Practices
▼
RESTAPI design best practices
# Versioning — always version your API
GET /api/v1/users # URL versioning (most common)
GET /api/users # with header: Accept: application/vnd.api.v2+json
# Pagination
GET /users?page=1&limit=20&sort=name&order=asc
# Response:
{
"data": [...],
"pagination": {
"page": 1, "limit": 20, "total": 250,
"pages": 13, "next": "/users?page=2&limit=20"
}
}
# Cursor-based pagination (better for large datasets)
GET /posts?cursor=abc123&limit=20
# Filtering, sorting, field selection
GET /users?role=admin&age[gte]=18&sort=-createdAt&fields=name,email
# Rate limiting response headers
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 995
X-RateLimit-Reset: 1713600000
# Consistent error format (always!)
{ error: { code, message, details, requestId } }
06
REST vs GraphQL
▼
RESTREST vs GraphQL
REST:
✅ Simple, widely understood
✅ Great HTTP caching
✅ Easy to reason about
❌ Over-fetching (too many fields)
❌ Under-fetching (multiple requests)
❌ Multiple endpoints per resource type
GraphQL:
✅ Single endpoint: POST /graphql
✅ Request exactly what you need (no over/under-fetching)
✅ Strongly typed schema
✅ Real-time via Subscriptions
❌ Harder caching
❌ More complex queries
❌ N+1 problem (use DataLoader)
# GraphQL query
query {
user(id: "123") {
name
email
orders {
id
total
items { name, price }
}
}
}
# REST equivalent might need:
GET /users/123
GET /users/123/orders
GET /orders/456/items # for each order
07
API Security
▼
BASHTesting APIs
# cURL
curl https://api.example.com/users
curl -X POST -H 'Content-Type: application/json' \
-H 'Authorization: Bearer token' \
-d '{"name":"Ali"}' https://api.example.com/users
curl -I https://api.example.com/users # headers only
curl -v https://api.example.com/users # verbose
# HTTPie (simpler than cURL)
http GET api.example.com/users
http POST api.example.com/users name=Ali email=ali@test.com
# Automated testing (Jest + supertest)
describe('POST /users', () => {
it('creates a user', async () => {
const res = await request(app)
.post('/api/users')
.set('Authorization', `Bearer ${token}`)
.send({ name: 'Ali', email: 'ali@test.com' });
expect(res.status).toBe(201);
expect(res.body.data.name).toBe('Ali');
});
});
# Python requests
import requests
response = requests.get('https://api.example.com/users',
headers={'Authorization': 'Bearer token'})
data = response.json()
08
Testing APIs
▼
RESTAPI Documentation (OpenAPI/Swagger)
# openapi.yaml
openapi: 3.0.0
info:
title: BitWithBite API
version: 1.0.0
paths:
/users:
get:
summary: List all users
parameters:
- name: page
in: query
schema: { type: integer, default: 1 }
responses:
'200':
description: List of users
content:
application/json:
schema:
type: object
properties:
data:
type: array
items: { $ref: '#/components/schemas/User' }
post:
summary: Create user
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/CreateUser' }
responses:
'201': { description: User created }
'422': { description: Validation error }
09
API Documentation
▼
❓ Quiz 1
Which HTTP method is idempotent and safe?
GET is both safe (no side effects) and idempotent (same result every time). PUT and DELETE are idempotent but not safe. POST is neither. PATCH is usually neither.
❓ Quiz 2
What HTTP status code should a successful resource creation return?
201 Created is the correct status for successful POST/resource creation. Include a Location header pointing to the new resource. 200 OK is for successful GETs. 204 No Content is for successful DELETEs with no response body.