All cheatsheets

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

{
"name":"Ada"string · required
"age":27integer · ≥ 0
}
Press validate to check the body field by field.

The schema is the contract — the server rejects any request that doesn't satisfy it.

55 entries

Design principles5

Be consistent across the whole API

Same naming, casing, and shapes everywhere

Principle of least surprise (POLA)

Behave the way an experienced developer expects

Never break existing clients

Additive changes are safe; removals/renames are not

Deprecation: true Sunset: Sat, 30 Nov 2024 23:59:59 GMT

Announce retirement of an endpoint with response headers

Errors are part of the contract

Document failure responses as carefully as success

Resource naming & URLs4

GET /users # not /getUsers

Use plural nouns for collections, no verbs in paths

GET /users/42/orders

Nest resources to express ownership (one level deep)

POST /orders/42/cancel

Model 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, cacheable

Read a resource; never changes server state

POST — not safe, NOT idempotent

Create a resource or run a non-idempotent action

PUT — not safe, IDEMPOTENT

Replace a resource entirely (full update / upsert)

PATCH — not safe, NOT (necessarily) idempotent

Partially update a resource (merge a subset of fields)

DELETE — not safe, IDEMPOTENT

Remove a resource

HEAD / OPTIONS

Metadata-only and capability-discovery methods

Status codes15

200 OK

Generic success with a representation in the body

201 Created

Resource created — include a Location header

202 Accepted

Request accepted for async processing (not yet done)

204 No Content

Success, but there is no body to return

301 / 302 / 304

Moved Permanently / Found / Not Modified

400 Bad Request

Malformed request the server cannot parse/understand

401 Unauthorized

Authentication is missing or invalid

403 Forbidden

Authenticated, but not allowed to do this

404 Not Found

No resource at this URL (or hidden for privacy)

405 Method Not Allowed

The URL exists, but not for this HTTP method

409 Conflict

Request conflicts with current resource state

410 Gone

Resource existed but is permanently removed

422 Unprocessable Entity

Valid syntax, but failed semantic/business validation

429 Too Many Requests

Client is rate-limited; back off and retry later

500 / 502 / 503 / 504

Server-side failures (your fault, not the client's)

Pagination, filtering & sorting6

GET /users?limit=20&offset=40

Offset pagination — simple, but drifts and gets slow

GET /users?limit=20&cursor=eyJpZCI6MTAyfQ

Cursor (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=50

Filtering — narrow a collection with query params

GET /users?sort=-created_at,name

Sorting — leading '-' means descending

GET /users?fields=id,name,email

Sparse fieldsets — return only requested fields

Error responses (RFC 9457)3

Content-Type: application/problem+json

One standard, machine-readable error shape for the whole API

{ "errors": [ { "field": "...", "detail": "..." } ] }

Field-level validation errors (problem+json extension)

Stable error 'type' URIs

Give 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+json

Media-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 / -Reset

Advertise the quota so clients self-throttle

Caching & content negotiation4

ETag: "a1b2c3" + If-None-Match

Conditional 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=60

Control 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