Cheatsheets
OpenAPI & REST
Resource design, methods, status codes, pagination, error shapes, versioning, and the OpenAPI document.
Visualize
OpenAPI — request validation
The schema is the contract — the server rejects any request that doesn't satisfy it.
Schema · the contract
required: [name, age]
properties:
name: { type: string }
age: { type: integer,
minimum: 0 }POST /users · request body
The schema is the contract — the server rejects any request that doesn't satisfy it.
55 entries
Design principles5
Be consistent across the whole APISame naming, casing, and shapes everywhere
Principle of least surprise (POLA)Behave the way an experienced developer expects
Never break existing clientsAdditive changes are safe; removals/renames are not
Deprecation: true
Sunset: Sat, 30 Nov 2024 23:59:59 GMTAnnounce retirement of an endpoint with response headers
Errors are part of the contractDocument failure responses as carefully as success
Resource naming & URLs4
GET /users # not /getUsersUse plural nouns for collections, no verbs in paths
GET /users/42/ordersNest resources to express ownership (one level deep)
POST /orders/42/cancelModel non-CRUD actions as a sub-resource verb
/api/v1/users (kebab-case path segments)Lowercase, hyphenated path segments
HTTP methods: safety & idempotency6
GET — safe, idempotent, cacheableRead a resource; never changes server state
POST — not safe, NOT idempotentCreate a resource or run a non-idempotent action
PUT — not safe, IDEMPOTENTReplace a resource entirely (full update / upsert)
PATCH — not safe, NOT (necessarily) idempotentPartially update a resource (merge a subset of fields)
DELETE — not safe, IDEMPOTENTRemove a resource
HEAD / OPTIONSMetadata-only and capability-discovery methods
Status codes15
200 OKGeneric success with a representation in the body
201 CreatedResource created — include a Location header
202 AcceptedRequest accepted for async processing (not yet done)
204 No ContentSuccess, but there is no body to return
301 / 302 / 304Moved Permanently / Found / Not Modified
400 Bad RequestMalformed request the server cannot parse/understand
401 UnauthorizedAuthentication is missing or invalid
403 ForbiddenAuthenticated, but not allowed to do this
404 Not FoundNo resource at this URL (or hidden for privacy)
405 Method Not AllowedThe URL exists, but not for this HTTP method
409 ConflictRequest conflicts with current resource state
410 GoneResource existed but is permanently removed
422 Unprocessable EntityValid syntax, but failed semantic/business validation
429 Too Many RequestsClient is rate-limited; back off and retry later
500 / 502 / 503 / 504Server-side failures (your fault, not the client's)
Pagination, filtering & sorting6
GET /users?limit=20&offset=40Offset pagination — simple, but drifts and gets slow
GET /users?limit=20&cursor=eyJpZCI6MTAyfQCursor (keyset) pagination — stable and fast at scale
Link: <...?cursor=abc>; rel="next"Advertise next/prev pages via the Link header (RFC 8288)
GET /orders?status=paid&min_total=50Filtering — narrow a collection with query params
GET /users?sort=-created_at,nameSorting — leading '-' means descending
GET /users?fields=id,name,emailSparse fieldsets — return only requested fields
Error responses (RFC 9457)3
Content-Type: application/problem+jsonOne standard, machine-readable error shape for the whole API
{ "errors": [ { "field": "...", "detail": "..." } ] }Field-level validation errors (problem+json extension)
Stable error 'type' URIsGive each error kind a permanent, documented identifier
Versioning3
GET /v1/users (URI versioning)Version in the path — explicit and cache-friendly
Accept: application/vnd.example.v2+jsonMedia-type (content negotiation) versioning
X-API-Version: 2 (custom header)Version via a dedicated request header
Auth, rate limiting & idempotency5
Authorization: Bearer <token>Standard way to send a token (OAuth 2 / JWT)
X-API-Key: <key> (or Authorization: Bearer)API keys for server-to-server / machine clients
Idempotency-Key: 6f3a... (on POST)Make unsafe POSTs safe to retry exactly once
Retry-After: 30 (with 429 or 503)Tell a throttled/over-capacity client how long to wait
RateLimit-Limit / -Remaining / -ResetAdvertise the quota so clients self-throttle
Caching & content negotiation4
ETag: "a1b2c3" + If-None-MatchConditional GET — skip the body when nothing changed (304)
If-Match: "a1b2c3" (optimistic concurrency)Reject a write if the resource changed under you (412)
Cache-Control: private, max-age=60Control how clients/CDNs cache the response
Accept + Content-Type (negotiation)Client states what it wants; server states what it sent
OpenAPI 3.1 document4
openapi: 3.1.0
info:
title: ...
version: ...The skeleton of an OpenAPI 3.1 specification
paths:
/orders/{id}:
get: { ... }An operation object: parameters, requestBody, responses
components:
schemas:
Order: { ... }Reusable schemas, parameters, and responses ($ref targets)
securitySchemes:
bearerAuth: { type: http, scheme: bearer }Declare how the API is authenticated