Returning the wrong HTTP status code is one of the most common API design mistakes. Returning 200 for errors, 404 when 403 is correct, or 500 when 422 would be more helpful — these mistakes make APIs harder to use and debug. This guide covers every status code that matters, with real examples and the common mistakes to avoid. This guide focuses on HTTP status codes, with the production trade-offs senior engineers need to make sound decisions.
⚡ TL;DR: 200=OK, 201=Created(+Location), 204=No Content, 301=Permanent Redirect, 304=Not Modified, 400=Bad Syntax, 401=Unauthenticated, 403=Unauthorized, 404=Not Found, 409=Conflict, 422=Validation Failed, 429=Rate Limited, 500=Server Bug, 502=Bad Gateway, 503=Service Unavailable.
2xx — Success codes — HTTP status codes
// 200 OK — general success, includes response body
GET /users/123 → 200 { id: 123, name: "Alice" }
PUT /users/123 → 200 { id: 123, name: "Alice Updated" }
// 201 Created — resource was created, include Location header
POST /users → 201
Location: /users/124
{ id: 124, name: "Bob" }
// 202 Accepted — request accepted, processing asynchronously
POST /reports/generate → 202
{ jobId: "job-abc-123", statusUrl: "/jobs/job-abc-123" }
// Client polls /jobs/job-abc-123 for completion
// 204 No Content — success with NO response body
DELETE /users/123 → 204 (empty body)
PUT /users/123/preferences → 204 (when you don't return updated resource)
// Never return body with 204 — clients won't read it3xx — Redirection codes
// 301 Moved Permanently — resource moved, update bookmarks
// Browser caches redirect: subsequent requests go directly to new URL
GET /api/v1/users → 301 Location: /api/v2/users
// 302 Found — temporary redirect (do NOT cache)
// Use for: temporary maintenance page, login redirects
// 304 Not Modified — conditional request, use cached version
// Client sends: If-None-Match: "etag-abc"
// Server: content unchanged → 304 (empty body, client uses cache)
// Massive bandwidth saving for static assets
// 307 Temporary Redirect — preserve HTTP method (unlike 302)
// POST to /login → 307 → POST forwarded to new URL
// 308 Permanent Redirect — preserve method (like 301 but keeps POST)4xx — Client error codes
// 400 Bad Request — malformed syntax, invalid JSON, missing required field
POST /users { name: null } → 400 { error: "name is required" }
// 401 Unauthorized — NOT authenticated (confusing name)
// Missing or invalid token
GET /profile → 401 { error: "Authentication required" }
WWW-Authenticate: Bearer
// 403 Forbidden — authenticated but NOT authorized
// User IS logged in but lacks permission
GET /admin/users → 403 { error: "Insufficient permissions" }
// 404 Not Found — resource does not exist
// Also use when you want to hide existence of forbidden resources
GET /users/999 → 404 { error: "User not found" }
// 409 Conflict — state conflict
POST /users { email: "existing@email.com" } → 409 { error: "Email already exists" }
PUT /orders/123 { version: 1 } → 409 { error: "Conflict: order was modified" }
// 422 Unprocessable Entity — valid syntax, invalid semantics
// JSON is valid but fails business rule validation
POST /users { age: -5 } → 422 { error: "Age must be positive" }
// 429 Too Many Requests — rate limited
GET /api/search → 429
Retry-After: 60
X-RateLimit-Reset: 17125344005xx — Server error codes
// 500 Internal Server Error — bug in your code
// Client did nothing wrong, you have a bug
// Log the full error server-side, return generic message to client
GET /users → 500 { error: "Something went wrong" }
// NEVER expose stack traces, DB queries, or internal paths to clients
// 502 Bad Gateway — upstream server returned invalid response
// Your server is fine, upstream (DB, microservice) returned garbage
// 503 Service Unavailable — server temporarily down
// Maintenance, overloaded, or circuit breaker open
GET /api → 503
Retry-After: 120
{ error: "Service temporarily unavailable" }
// 504 Gateway Timeout — upstream took too long
// Your server waited too long for DB or microserviceCommon mistakes to avoid
- ❌ 200 for errors — never return
{ status: 200, error: "Not found" } - ❌ 404 when 403 is correct — leaks resource existence; sometimes intentional
- ❌ 400 for validation failures — use 422 for business rule violations
- ❌ 500 for client errors — 500 means YOUR code has a bug, not theirs
- ❌ 200 with empty body — use 204 when there is no content to return
- ✅ 201 + Location header on resource creation
- ✅ 429 + Retry-After for rate limiting
- ✅ 401 + WWW-Authenticate for unauthenticated requests
Status codes are foundational to the REST API design guide — every design decision there depends on using the right status code. External reference: MDN HTTP status codes reference.
Recommended Reading
→ Designing Data-Intensive Applications — The essential book every senior developer needs. Covers distributed systems, databases, and production architecture.
→ The Pragmatic Programmer — Timeless engineering wisdom for writing better, more maintainable code at any level.
Affiliate links. We earn a small commission at no extra cost to you.
Free Weekly Newsletter
🚀 Don’t Miss the Next Cheat Code
Join 1,000+ senior developers getting expert-level JS, Python, AWS, system design and AI secrets every week. Zero fluff, pure signal.
Related: JavaScript Array Methods: Every Method Explained With Real Examples · Vibe Coding: How Senior Developers Actually Use AI to Write Code Faster · Prompt Engineering for Developers: Patterns That Produce Production-Ready Code Every Time
Related: JavaScript Array Methods: Every Method Explained With Real Examples · Terraform for Developers: Infrastructure as Code From Zero to Production AWS · Python String Methods: Every str Method With Real Production Examples
Watch: 100 Days of AI on YouTube
Short videos from CheatCoders, one AI engineering topic per day.
Most viewed
- Python Decorators Explained: From Simple Wrappers to Production Patterns
- Claude Code vs Cursor vs GitHub Copilot: Choose by Workflow, and Set Up One Repo That Works With All Three
- AI Agent Frameworks in 2025: LangGraph vs CrewAI vs AutoGen vs Raw API
- Python String Methods: Every str Method With Real Production Examples
- REST API Design Best Practices: The Patterns That Make APIs a Joy to Use
Newly added
- AWS Systems Manager Parameter Store: Hierarchical Runtime Config for Coding Agents
- Amazon Cognito Identity Pools: Federate Coding-Agent Tool Callers Without Long-Lived Keys
- Amazon Athena for Coding Agents: Query Tool Audit Logs and Eval Traces on S3 Without a Warehouse
- AWS Batch for Coding Agents: Parallel Overnight PR Reviews and Long-Running Jobs Without Lambda Timeouts
- Amazon Bedrock Prompt Management: Version and A/B Test Coding-Agent System Prompts
Deep-dive PDF
Get the expanded guide for this post — extra diagrams-style checklists, failure modes, and a production walkthrough. Free when you subscribe to CheatCoders.
Already subscribed? or open the subscribe page.
Discover more from CheatCoders
Subscribe to get the latest posts sent to your email.
