# HTTP status codes and what a program should do next

A quick reference for software calling web APIs: what each common status code means, and a sensible next step. Meanings follow RFC 9110 (HTTP Semantics) and MDN; the retry column is general guidance, not part of the standard. Whether any retry is safe depends on the request, not just the status: repeat only idempotent requests (GET, PUT, DELETE, or a POST with an idempotency key), and check whether a timed-out write already happened before repeating it.

@sheet Status codes
@width A: 70
@width B: 170
@width C: 320
@width D: 190
@width E: 400
@style A1:E1: bold
| Code | Name | What it means | Retry? | What to do next |
| --- | --- | --- | --- | --- |
| 200 | OK | Request succeeded | n/a | Use the response body |
| 201 | Created | A new resource was made | No | Save the Location header or returned ID; repeating the request would create a duplicate |
| 202 | Accepted | Work queued, not finished | n/a | Poll the status URL with a delay until done |
| 204 | No Content | Success with no body | n/a | Treat as done |
| 301 | Moved Permanently | Resource has a new permanent URL | n/a | Follow the Location URL and update the stored URL. Older clients may rewrite POST as GET; do not forward credentials or a request body to a different origin without checking it |
| 302 | Found | Temporary redirect | n/a | Follow for GET requests. Per the Fetch standard a POST is redirected as GET, so do not rely on the method surviving; keep the original URL as the canonical one |
| 304 | Not Modified | Cached copy is still current | n/a | Use the cache |
| 307 | Temporary Redirect | Temporary redirect; method and body are preserved | n/a | The same request, body included, is resent to the Location URL. Only follow if you trust that origin with the same body and credentials |
| 308 | Permanent Redirect | Permanent redirect; method and body are preserved | n/a | As 307, but update the stored URL. Same caution about resending bodies and credentials across origins |
| 400 | Bad Request | The request is malformed | No | Fix the request; repeating it unchanged will fail again |
| 401 | Unauthorized | Missing, expired or invalid credentials | Once | Refresh or re-check credentials once, then stop and report |
| 403 | Forbidden | Server understood the request but refuses it; re-authenticating usually makes no difference | No | Stop and report. A 403 does not prove the credentials are valid; the refusal is tied to permissions or application logic |
| 404 | Not Found | Nothing found at this URL, or the server is concealing it | No | Check the URL for typos. Note a 404 can be sent instead of 403 to avoid revealing that a resource exists |
| 405 | Method Not Allowed | Wrong HTTP method for this URL | No | Read the Allow header and the API docs |
| 408 | Request Timeout | Server closed a slow or idle connection | Only if idempotent | The request may not have been fully received; retry a safe request on a new connection |
| 409 | Conflict | State changed under you | After refetch | Fetch the current state, merge, then resubmit |
| 410 | Gone | Removed on purpose, permanently | No | Drop the link from your records |
| 413 | Content Too Large | Body exceeds the size limit | No | Shrink or split the body |
| 415 | Unsupported Media Type | Wrong Content-Type | No | Send a supported type |
| 422 | Unprocessable Content | Well-formed but rejected by validation | No | Read the error detail, fix the data, resubmit |
| 429 | Too Many Requests | Rate limit hit | Later | Wait for the Retry-After time if given, then slow down |
| 500 | Internal Server Error | Server-side fault | Only if idempotent | Retry a few times with backoff; a failed-looking write may still have happened, so check first |
| 502 | Bad Gateway | An upstream server failed | Only if idempotent | Retry with backoff; often transient |
| 503 | Service Unavailable | Overloaded or down | Only if idempotent | Honour Retry-After if present; retry with backoff |
| 504 | Gateway Timeout | Upstream was too slow | Only if idempotent | Check whether the write happened before retrying |
@endsheet

## Retry rules of thumb

- Only repeat idempotent requests, or requests carrying an idempotency key. Idempotent methods are GET, HEAD, PUT and DELETE; a plain POST is not.
- Back off exponentially (for example 1s, 2s, 4s, 8s) and add random jitter so many clients do not retry together.
- Cap the attempts (3 to 5) and the total wait, then report the failure instead of looping.
- Obey a Retry-After header over your own schedule.
- Never retry 400, 403, 404 or 422 unchanged.
- On redirects, do not let an Authorization header or request body leak to a different origin; many HTTP clients strip credentials on cross-origin redirects for this reason.

Sources: RFC 9110 (HTTP Semantics), https://www.rfc-editor.org/rfc/rfc9110.html, and the MDN Web Docs HTTP status reference, https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status
