What is the difference between 401 and 403?
401 Unauthorized means the client is not authenticated — either no credentials were provided or they are invalid. Despite the name, it really means "unauthenticated." 403 Forbidden means the client is authenticated (the server knows who they are) but does not have permission to access the resource. Use 401 for login failures and missing tokens; use 403 for insufficient role or permission.
Should I return 200 with an error message or a 4xx status code?
Always use the correct HTTP status code. Returning 200 with an error in the body (e.g., {"status": "error"}) breaks HTTP semantics. Clients, proxies, CDNs, and monitoring tools all use the status code to determine success or failure. A 200 response with an error body will be cached by CDNs, counted as a success in metrics, and confuse every tool in the chain.
When should I use 400 vs 422?
400 Bad Request means the request is malformed — invalid JSON syntax, missing required headers, or wrong content type. The server cannot even parse the request. 422 Unprocessable Entity means the request is well-formed (valid JSON, correct structure) but semantically invalid — like an email field containing "not-an-email" or a date in the past for a future booking. Many APIs use 400 for both; 422 is more precise.
What does the 429 Too Many Requests status code mean?
The 429 status code means the client has sent too many requests in a given time window and has been rate-limited. The server should include a Retry-After header indicating how many seconds the client should wait before retrying. This code is essential for API rate limiting and protects your server from abuse or accidental request storms from buggy clients.
Should I return 404 or 403 for resources the user cannot access?
It depends on your security model. Returning 403 confirms the resource exists but the user lacks access, which may leak information. Returning 404 hides the resource's existence entirely, which is more secure. Use 404 when you do not want to reveal whether a resource exists (e.g., other users' private data). Use 403 when the resource is known to exist and the user should understand they need different permissions.