2xx SuccessThe request was received, understood and accepted.
The request succeeded and the body contains the result.
- When to return it
- Successful GET, successful PUT/PATCH that returns the updated resource, or an action that returns a result.
- What to verify
- Assert the status AND the body: schema, values and Content-Type. A 200 alone proves very little. Check that error conditions never come back as 200.
Common bugs
- ✕200 with an error body such as {"success": false, "error": "..."}; monitoring and clients treat it as success.
- ✕200 for a POST that created a resource where 201 + Location is documented.
- ✕200 with an empty body where the schema promises data.
The request created a new resource.
- When to return it
- Successful POST (or PUT to a new URI) that creates a resource.
- What to verify
- Verify the Location header points to the new resource, the body (if any) contains the server-generated id, and a follow-up GET returns the same data.
Common bugs
- ✕Missing or relative-but-wrong Location header.
- ✕Resource returned before it is actually persisted (GET right after returns 404).
The request was accepted for processing, which has not finished.
- When to return it
- Asynchronous jobs: exports, bulk imports, long-running operations.
- What to verify
- Verify the response tells you how to track the job (a status URL in Location or the body). Poll it to completion and test the failure path of the job too.
Common bugs
- ✕No way to find out whether the job later failed.
- ✕Job status endpoint reachable by other users.
Success, but the payload was modified by a transforming proxy.
- When to return it
- Set by intermediaries, not by origin APIs.
- What to verify
- If you see it, something between client and server is rewriting responses. Compare with a direct call to the origin.
Success with no response body.
- When to return it
- Successful DELETE, or PUT/PATCH where the API does not return the resource.
- What to verify
- Assert the body is truly empty (Content-Length: 0 or absent body). Client code that calls response.json() on a 204 will throw, so check consumers handle it.
Common bugs
- ✕204 sent with a body (some proxies drop it, others hang).
- ✕Client crashes parsing an empty body as JSON.
Success; the client should reset the document view (e.g. clear a form).
- When to return it
- Rare; form-submission UIs.
- What to verify
- Must not contain a body. Rarely used by REST APIs.
The body contains only the byte range(s) requested with a Range header.
- When to return it
- Resumable downloads and media streaming.
- What to verify
- Request Range: bytes=0-99 and verify 206, Content-Range: bytes 0-99/<total> and exactly 100 bytes. Test an unsatisfiable range (expect 416) and multiple ranges.
Common bugs
- ✕Content-Range total wrong, breaking resumed downloads.
- ✕Server ignores Range and returns 200 with the full file while advertising Accept-Ranges: bytes.
207RFC 4918 §11.1 (WebDAV)The body contains separate status codes for multiple sub-operations.
- When to return it
- Batch operations where items can succeed or fail independently.
- What to verify
- Never stop at the top-level 207: assert the status of every item in the body, and include a batch where some items fail.
Common bugs
- ✕Tests pass because they only check the outer 207 while individual items failed.
Members of a binding were already listed earlier in the same 207 response.
- When to return it
- WebDAV bindings only.
- What to verify
- Not expected from REST APIs.
The response is the result of instance manipulations (delta encoding).
- When to return it
- Delta encoding; practically unused.
- What to verify
- Not expected from REST APIs.
4xx Client errorThe request is wrong; retrying it unchanged will fail again.
The server cannot process the request because it is malformed.
- When to return it
- Unparseable JSON, wrong types, missing required parameters, invalid query values.
- What to verify
- Send malformed JSON, wrong types and missing fields. Expect 400 (or 422) with an error body that names the field. It must never be a 500.
Common bugs
- ✕500 Internal Server Error for invalid input (unhandled exception).
- ✕Generic message with no field name, making the error unactionable.
- ✕Error body leaks stack traces or SQL.
Authentication is missing or invalid. Despite the name, it means "unauthenticated".
- When to return it
- No credentials, malformed credentials, expired or revoked tokens.
- What to verify
- Test no token, malformed token, expired token, token signed with the wrong key and a revoked token. Expect 401 with a WWW-Authenticate header and no resource data.
Common bugs
- ✕403 returned where 401 is correct (or the reverse).
- ✕Missing WWW-Authenticate header.
- ✕Expired tokens still accepted.
402rareRFC 9110 §15.5.3 (reserved)Reserved for future use; some APIs use it for billing problems.
- When to return it
- Non-standard: quota or subscription exhausted, if the API documents it.
- What to verify
- Only test if documented. Check the error body explains what to do.
The client is authenticated (or authentication would not help) but is not allowed to do this.
- When to return it
- Missing role or scope, accessing another tenant's data, blocked IPs.
- What to verify
- Use a valid token from a user without the permission and confirm 403 with no side effects. Check object-level authorisation: user A must not read or modify user B's resources by changing an id.
Common bugs
- ✕Broken object-level authorisation (BOLA/IDOR): 200 with another user's data.
- ✕Action performed even though 403 is returned.
The server has no resource at this URI (or will not reveal that it exists).
- When to return it
- Unknown ids or paths. Also acceptable instead of 403 to hide the existence of resources.
- What to verify
- Request a non-existent id, a deleted id and a malformed path. Expect 404 with a consistent error body. An empty collection should be 200 with [], not 404.
Common bugs
- ✕404 for an empty list.
- ✕500 when the id has the wrong format.
- ✕Different responses for "exists but forbidden" and "missing" that allow enumeration.
The resource exists but does not support this method.
- When to return it
- e.g. DELETE on a read-only collection.
- What to verify
- Send unsupported methods and verify 405 with an Allow header listing the supported methods.
Common bugs
- ✕404 or 500 instead of 405.
- ✕Missing Allow header.
No representation matches the Accept headers.
- When to return it
- Client asks for a media type the API cannot produce (e.g. Accept: application/xml on a JSON-only API).
- What to verify
- Send Accept: application/xml and check for 406 or documented fallback to JSON.
Like 401 but for a proxy between client and server.
- When to return it
- Corporate proxies.
- What to verify
- Usually an environment problem in CI rather than an API defect. Configure proxy credentials.
The server timed out waiting for the client to send the request.
- When to return it
- Slow or stalled uploads; idle connections.
- What to verify
- Not the same as a slow server (that is 504 at a gateway, or a client-side timeout). Simulate a slow upload if relevant.
The request conflicts with the current state of the resource.
- When to return it
- Duplicate unique values (email already registered), version conflicts, invalid state transitions.
- What to verify
- Create a duplicate (same email/SKU) and expect 409 with a clear message. Fire two concurrent updates and check one wins cleanly.
Common bugs
- ✕500 from an unhandled unique-constraint violation.
- ✕Duplicate records created under concurrency.
The resource was intentionally removed and will not come back.
- When to return it
- Retired API versions or permanently deleted resources.
- What to verify
- For sunset API versions, verify 410 after the sunset date and that the error points to the replacement.
The server requires a Content-Length header.
- When to return it
- Servers that refuse chunked uploads.
- What to verify
- Send a body with chunked transfer encoding and no Content-Length if the API documents this restriction.
A conditional header such as If-Match did not match.
- When to return it
- Optimistic concurrency: PUT/PATCH with If-Match carrying a stale ETag.
- What to verify
- GET (save ETag), modify the resource elsewhere, then PUT with If-Match: <old etag>. Expect 412 and no change.
Common bugs
- ✕If-Match ignored, so lost updates happen silently.
The request body is larger than the server allows (formerly "Payload Too Large").
- When to return it
- Uploads or JSON bodies over the documented limit.
- What to verify
- Send a body just over the limit. Expect 413 quickly, not a timeout, a dropped connection or a 500.
Common bugs
- ✕Limit enforced only at the proxy, producing an HTML error page instead of JSON.
The request URI is longer than the server will interpret.
- When to return it
- Very long query strings (huge filters or id lists).
- What to verify
- Send a query string of several kilobytes. If filters can grow large, the API should offer a POST search endpoint.
The request body's Content-Type is not supported.
- When to return it
- Body sent as text/plain or XML to a JSON-only endpoint; missing Content-Type.
- What to verify
- Send a valid JSON body with Content-Type: text/plain and with no Content-Type. Expect 415 (or a documented 400).
Common bugs
- ✕Body silently ignored and the request processed with defaults.
The requested Range cannot be served.
- When to return it
- Range starts beyond the end of the file.
- What to verify
- Request a range past the end and expect 416 with Content-Range: bytes */<total>.
The Expect header could not be met.
- When to return it
- Unsupported Expect values.
- What to verify
- Rare. Send an unknown Expect value if you are testing an HTTP server itself.
418rareRFC 2324 (April Fools); reserved as unused by RFC 9110 §15.5.19A joke code from the Hyper Text Coffee Pot Control Protocol.
- When to return it
- Never in production. Some services use it as a deliberately odd response to bots.
- What to verify
- If a real API returns 418, file a bug or confirm it is a documented anti-bot response. Useful as an "unexpected status" in client error-handling tests.
The request reached a server that cannot produce a response for this origin.
- When to return it
- HTTP/2 connection reuse across hostnames with mismatched certificates.
- What to verify
- Seen with shared CDN/TLS setups. Usually an infrastructure configuration issue.
The body is syntactically valid but semantically invalid.
- When to return it
- Validation failures: end date before start date, unknown enum value, business rule violations.
- What to verify
- Check the API is consistent: one convention for validation errors (400 or 422) across all endpoints, with a machine-readable list of field errors.
Common bugs
- ✕Mix of 400 and 422 for the same kind of error across endpoints.
- ✕Only the first validation error reported.
423rareRFC 4918 §11.3 (WebDAV)The resource is locked.
- When to return it
- Locked documents or accounts, if documented.
- What to verify
- If used for locked accounts, check the message does not reveal whether the account exists.
424rareRFC 4918 §11.4 (WebDAV)The request failed because a previous request it depended on failed.
- When to return it
- Items inside a batch/multi-status response.
- What to verify
- Check dependent items in a batch report 424 rather than a misleading success.
The server will not process a request that might be replayed (TLS 1.3 early data).
- When to return it
- Non-idempotent requests received as TLS 0-RTT early data.
- What to verify
- Relevant for edge/CDN setups with 0-RTT enabled: non-idempotent requests must not be processed from early data.
The client must switch to a different protocol named in Upgrade.
- When to return it
- e.g. requiring a newer protocol version.
- What to verify
- Verify the Upgrade header names the required protocol.
The server requires the request to be conditional (e.g. include If-Match).
- When to return it
- APIs that enforce optimistic locking on updates.
- What to verify
- Send PUT/PATCH without If-Match and expect 428; with a current ETag expect success; with a stale one expect 412.
The client has sent too many requests in a given time (rate limiting).
- When to return it
- Rate or quota limits exceeded.
- What to verify
- Exceed the limit in a loop. Expect 429 with Retry-After, accurate rate limit headers, and recovery after the window. Confirm limits are per client/key and cannot be bypassed by changing headers like X-Forwarded-For.
Common bugs
- ✕No Retry-After header.
- ✕Limit keyed on a spoofable header.
- ✕503 or 500 used for throttling.
Headers (or a single header) are too large.
- When to return it
- Oversized cookies or tokens.
- What to verify
- Send a very large cookie or Authorization header. Large JWTs with many claims can trigger this in production.
The resource is unavailable because of a legal demand.
- When to return it
- Geo-blocked or legally removed content.
- What to verify
- If used, verify a Link header with rel="blocked-by" where appropriate and that the reason is explained.
5xx Server errorThe server failed to fulfil a valid request.
An unexpected condition prevented the server from fulfilling the request.
- When to return it
- Genuinely unexpected failures only. Never as a response to bad client input.
- What to verify
- Any 500 you can trigger with crafted input is a bug: the input should get a 4xx. Check that the body is a generic error with a correlation id, not a stack trace.
Common bugs
- ✕500 for validation errors, malformed JSON or a wrong id format.
- ✕Stack traces, SQL or file paths in the body.
- ✕Partial writes left behind after the failure.
The server does not support the functionality required (often an unknown method).
- When to return it
- Methods the server does not recognise at all.
- What to verify
- For a known method on a resource that does not allow it, 405 is correct, not 501.
A gateway or proxy got an invalid response from the upstream server.
- When to return it
- Set by load balancers/gateways when the app crashes or closes the connection.
- What to verify
- Usually means the application process died or rejected the connection. Correlate with app logs; check the gateway returns a JSON error body for API clients.
The server is temporarily unable to handle the request (overload or maintenance).
- When to return it
- Maintenance windows, overload shedding, dependency outages; health checks reporting unhealthy.
- What to verify
- Check Retry-After is present during maintenance and that clients back off. Verify health endpoints return 503 when a critical dependency is down.
Common bugs
- ✕Health check returns 200 while the database is down.
A gateway or proxy did not get a timely response from upstream.
- When to return it
- Upstream exceeds the gateway timeout.
- What to verify
- Find slow paths (large exports, unindexed filters). The operation may still complete on the server after the 504, so check for duplicate side effects on retry.
Common bugs
- ✕Client retries a POST after 504 and creates duplicates (no idempotency key).
The HTTP version used in the request is not supported.
- When to return it
- Protocol-level mismatch.
- What to verify
- Rare; only relevant when testing HTTP servers or proxies.
Server misconfiguration in transparent content negotiation.
- When to return it
- Practically never.
- What to verify
- Indicates a server configuration error.
507rareRFC 4918 §11.5 (WebDAV)The server cannot store the representation needed to complete the request.
- When to return it
- Storage quota or disk full, if the API documents it.
- What to verify
- If used for user quotas, confirm the message is clear; quotas exceeded by the user are arguably 4xx.
The server detected an infinite loop while processing.
- When to return it
- WebDAV bindings.
- What to verify
- Not expected from REST APIs.
510rareRFC 2774 (historic)Further extensions to the request are required.
- When to return it
- Obsolete.
- What to verify
- Should not appear in modern APIs.
The client must authenticate to gain network access (captive portals).
- When to return it
- Captive portals on public Wi-Fi, not origin servers.
- What to verify
- If tests in CI or on a device suddenly see 511 or HTML, the network is intercepting traffic.