An HTTP method is safe if it is intended to be read-only and must not cause side effects: GET and HEAD are the canonical examples. RFC 7231 defines GET, HEAD, PUT, DELETE, and (practically) OPTIONS and TRACE as idempotent—repeated identical calls leave the server in the same observable state. Understanding the difference is crucial because retries in distributed systems depend on it. PUT and DELETE are idempotent even though DELETE may change a 200 to a 404 the second time; what matters is that no additional side effects occur beyond the first successful call. PUT and PATCH are often confused: PUT replaces the entire resource with the submitted representation, while PATCH applies a partial change to specific fields.
Testing PATCH endpoints is harder because the format varies. JSON Merge Patch (application/merge-patch+json) describes changes by including fields to update, setting fields to null to remove them, and omitting fields to leave them untouched, whereas JSON Patch (application/json-patch+json, RFC 6902) describes a sequence of operations such as add, remove, replace, move, copy, and test. Tests for PATCH must carefully cover missing fields, null values, and unknown fields to ensure the server preserves the rest of the resource. For state-changing operations—especially POST—clients can send an Idempotency-Key header so the server can deduplicate retries and avoid duplicate side effects. Request validation at the API layer checks that an incoming request meets the contract—required fields present, types correct, values within allowed ranges, and business rules satisfied—before any business logic runs.
Headers carry much of the metadata HTTP services depend on. The Location header in a 201 response gives clients a canonical URI for the newly created resource. The ETag header carries an opaque token representing a specific resource version, used both for caching (If-None-Match produces 304 Not Modified) and for optimistic concurrency control: if a client sends If-Match with a write request and the resource has changed, the server responds with 412 Precondition Failed. WWW-Authenticate, sent with 401, tells the client which authentication scheme is required and any parameters; Retry-After, paired with 429, 503, and sometimes 3xx, tells the client how long to wait. For errors, RFC 7807 Problem Details (application/problem+json) provides a standardized shape containing at least type, title, status, and detail, with an optional instance URI—a much better format than ad-hoc JSON for telling clients what field failed, why it failed, and how to fix the request. Content negotiation lets clients request representations via Accept, Accept-Language, or Accept-Encoding, and the Vary response header tells caches which request headers the response depends on so caches do not serve the wrong variant to later clients.