RESTful APIs cheat sheet
A scannable RESTful APIs reference: 20 short snippets across 11 topics, each linking back to the lesson it came from.
At a glance
| Topic | What it covers | |
|---|---|---|
| Resource modelling and methods | REST is a style built on one idea: identify things with URLs, and use HTTP's methods to act on them. A resource is a | lesson |
| Status codes, pagination and filtering | A client should be able to decide what to do from the status line alone: retry, re-authenticate, or stop. Returning 200 | lesson |
| Versioning and error shapes | Every failure should look the same, so a client can handle errors generically and add special cases only where it must | lesson |
| Content negotiation and media types | Accept and Content-Type are how a client and a server agree on representation, and getting the failure codes right | lesson |
| Authentication and authorisation | Choosing between API keys, OAuth 2.0 and signed tokens, and validating what you accept rather than trusting what it | lesson |
| Caching with ETag and Cache-Control | Validators and directives let a client skip a body it already has, which is the cheapest performance work available on | lesson |
| Idempotency, retries and rate limiting | Networks fail after the server has done the work. Idempotency keys make a retried write safe, and honest rate limits | lesson |
| Handling uploads and binary payloads | Small files can go through the API. Large ones should not, and pre-signed URLs move the bytes without touching your | lesson |
| Long-running operations, webhooks and bulk endpoints | Some work cannot finish inside an HTTP request. Returning 202 with a status resource is the pattern that keeps clients | lesson |
| Testing and contract testing REST APIs | Test the failures as carefully as the happy path, and let a contract test catch the change that would break a client | lesson |
| REST compared with GraphQL, gRPC and tRPC | Pick the protocol that matches the shape of the data and the shape of the clients, and expect to run more than one | lesson |
Quick snippets
Resource modelling and methods
Model nouns, not actions
GET /orders # the collection
POST /orders # create one; server assigns the id
GET /orders/1042 # a single order
PATCH /orders/1042 # change part of it
DELETE /orders/1042 # remove it
GET /orders/1042/items # a sub-collection
PUT /orders/1042/items/3 # replace one line item
URL design rules that age well
# an action that does not fit CRUD: model it as a resource instead of a verb
POST /orders/1042/cancellation # creates a cancellation
{ "reason": "customer_request" }
# if the client must not create duplicates on retry, use an idempotency key
POST /payments HTTP/1.1
Idempotency-Key: 8f14e45f-ea3b-4c2d-9f10-2c3d4e5f6a7b
Content-Type: application/json
{ "amount": 2500, "currency": "USD", "order_id": "1042" }
Representations and content negotiation
GET /orders/1042 HTTP/1.1
Accept: application/json
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
ETag: "7f2c9a"
Cache-Control: private, max-age=60
{ "id": "1042", "status": "shipped", "total": { "amount": 2500, "currency": "USD" } }Full lesson: Resource modelling and methods →
Status codes, pagination and filtering
Offset versus cursor pagination
GET /orders?status=shipped&per_page=50&page=3 HTTP/1.1
HTTP/1.1 200 OK
Link: <https://api.example.com/orders?status=shipped&per_page=50&page=4>; rel="next",
<https://api.example.com/orders?status=shipped&per_page=50&page=9>; rel="last"
X-Total-Count: 412
{ "data": [ { "id": "1042" } ], "meta": { "page": 3, "per_page": 50, "total": 412 } }
Offset versus cursor pagination
GET /orders?status=shipped&limit=50&cursor=eyJpZCI6MTA0Mn0 HTTP/1.1
HTTP/1.1 200 OK
Link: <https://api.example.com/orders?status=shipped&limit=50&cursor=eyJpZCI6MTA5Mn0>; rel="next"
{ "data": [ { "id": "1042" } ], "next_cursor": "eyJpZCI6MTA5Mn0" }
Filtering, sorting and field selection
GET /orders?status=shipped&created_after=2026-01-01
GET /orders?status=shipped&status=refunded # repeated = OR
GET /orders?sort=-created_at,total # - means descending
GET /orders?fields=id,status,total # sparse fieldsets
GET /orders?include=customer,items # related resources
GET /orders?q=laptop+stand # free-text searchFull lesson: Status codes, pagination and filtering →
Versioning and error shapes
Strategies for change
# deprecated endpoint: tell clients before you remove anything
HTTP/1.1 200 OK
Deprecation: Sat, 01 Aug 2026 00:00:00 GMT
Sunset: Mon, 01 Feb 2027 00:00:00 GMT
Link: <https://api.example.com/v2/orders>; rel="successor-version"
Making change survivable
{
"data": { "id": "1042", "status": "shipped" },
"meta": { "request_id": "01J8Z4K2M9QH", "deprecated": ["status_detail"] },
"links": { "self": "/v2/orders/1042" }
}Full lesson: Versioning and error shapes →
Content negotiation and media types
The two headers and what they mean
GET /articles/42 HTTP/1.1
Accept: application/json, text/csv;q=0.5, */*;q=0.1
The two headers and what they mean
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Vary: Accept
{"id":42,"title":"Caching","status":"published"}Full lesson: Content negotiation and media types →
Authentication and authorisation
Choosing a mechanism
POST /oauth/token HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&scope=orders:write&client_id=svc-billing
# client_secret goes in the body or, preferably, in HTTP Basic auth
Choosing a mechanism
GET /orders HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImtfMSJ9...Full lesson: Authentication and authorisation →
Caching with ETag and Cache-Control
Conditional requests
PUT /articles/42 HTTP/1.1
If-Match: "9f2b1c"
Content-Type: application/json
{"title":"Caching, revised"}
HTTP/1.1 412 Precondition Failed
# someone else updated the article first; reload and retryFull lesson: Caching with ETag and Cache-Control →
Idempotency, retries and rate limiting
Idempotency keys
POST /payments HTTP/1.1
Idempotency-Key: 8f14e45f-ceea-467a-9f6f-3f2b1c9d4a77
Content-Type: application/json
{"amount":2500,"currency":"GBP","reference":"INV-1041"}
Retry strategy and rate limiting
HTTP/1.1 429 Too Many Requests
Retry-After: 30
RateLimit-Limit: 100
RateLimit-Remaining: 0
RateLimit-Reset: 30Full lesson: Idempotency, retries and rate limiting →
Handling uploads and binary payloads
Small uploads through the API
POST /avatars HTTP/1.1
Content-Type: multipart/form-data; boundary=----X
------X
Content-Disposition: form-data; name="file"; filename="me.png"
Content-Type: image/png
...binary...
------X--
Large uploads and downloads
# Range requests let a client resume a download in pieces
from flask import Response
def send_range(path: str, start: int, end: int, total: int) -> Response:
with open(path, "rb") as fh:
fh.seek(start)
chunk = fh.read(end - start + 1)
return Response(chunk, 206, headers={
"Content-Range": "bytes " + str(start) + "-" + str(end) + "/" + str(total),
"Accept-Ranges": "bytes",
"Content-Length": str(len(chunk)),
})Full lesson: Handling uploads and binary payloads →
Long-running operations, webhooks and bulk endpoints
202 and a status resource
POST /reports HTTP/1.1
Content-Type: application/json
{"from":"2026-01-01","to":"2026-06-30","format":"csv"}
HTTP/1.1 202 Accepted
Location: /operations/7f3c9a1e
Retry-After: 5
{"id":"7f3c9a1e","state":"pending"}Full lesson: Long-running operations, webhooks and bulk endpoints →
Testing and contract testing REST APIs
Contract testing in practice
# The provider verifies every consumer's contracts before it can ship
pact-verifier --provider-base-url=http://localhost:8080 \
--pact-url=./pacts/reporting-service-orders-api.json
# And a breaking-change check on the specification itself
oasdiff breaking --base main:openapi.yaml --revision HEAD:openapi.yamlFull lesson: Testing and contract testing REST APIs →
REST compared with GraphQL, gRPC and tRPC
The honest comparison
# GraphQL solves the aggregate screen: one request, exactly the fields needed
query OrderScreen($id: ID!) {
order(id: $id) {
id
status
total { amount currency }
customer { name }
items(first: 5) { sku name }
}
}
# The same screen over REST is typically four calls, or one bespoke endpoint
# that exists only to serve this one page.Full lesson: REST compared with GraphQL, gRPC and tRPC →
FAQ
Is this RESTful APIs cheat sheet free to use?
Where do the examples come from?
How do I go deeper than a cheat sheet?
Related cheat sheets
XML XPath XSLT SOAP RSS & Atom
Last refreshed 2026-09-27.