HTTP status codes — which code to return and when
2xx success codes, 3xx redirects, 4xx client errors, 5xx server errors, 201 vs 200, 400 vs 422, 401 vs 403, 404 vs 410
Choosing the Right HTTP Status Code
Returning 200 for everything and hiding errors in the body is an anti-pattern. Clients, monitoring tools, and proxies all rely on status codes to route behavior correctly.
Most Used Codes
200 OK — Request succeeded. Use for GET, PUT, PATCH responses with a body.
201 Created — Resource was created. Always include a Location header pointing to the new resource.
204 No Content — Success with no body. Use for DELETE.
400 Bad Request — Malformed request syntax or missing required fields.
401 Unauthorized — Not authenticated. The client must provide credentials.
403 Forbidden — Authenticated but not authorized. You know who they are; they just cannot do this.
404 Not Found — Resource does not exist.
422 Unprocessable Entity — Request was well-formed but failed validation rules.
429 Too Many Requests — Rate limit exceeded.
500 Internal Server Error — Something broke on the server.
// 201 Created with Location header
res.status(201)
.header('Location', `/users/${newUser.id}`)
.json(newUser);
// 422 with validation errors
res.status(422).json({
errors: [
{ field: 'email', message: 'Must be a valid email address' }
]
});