Restful Status Codes
title: "RESTful Status Codes — Choosing the Right HTTP Status Codes" description: "RESTful HTTP status codes communicate operation results clearly with 2xx for success, 4xx for client errors, and 5xx for server errors following REST conventions." date: 2026-06-28 lastmod: 2026-06-28 weight: 12 tags: [apis, restful] }
RESTful status codes use HTTP status codes to communicate operation results: 200 OK for success, 201 Created for new resources, 204 No Content for deletions.
What You'll Learn
- Common RESTful status codes
- Status code categories
- Choosing the right code
Why It Matters
Correct status codes enable standard HTTP client behavior. Wrong codes confuse clients and break error handling.
Status Code Reference
| Code | Name | When to Use |
|---|---|---|
| 200 | OK | Successful GET, PUT, PATCH |
| 201 | Created | Successful POST (new resource) |
| 204 | No Content | Successful DELETE, PUT (no body) |
| 301 | Moved Permanently | Resource relocated |
| 400 | Bad Request | Invalid input, malformed request |
| 401 | Unauthorized | Missing or invalid authentication |
| 403 | Forbidden | Authenticated but not authorized |
| 404 | Not Found | Resource doesn't exist |
| 405 | Method Not Allowed | Wrong HTTP method |
| 409 | Conflict | Resource state conflict |
| 422 | Unprocessable Entity | Validation errors |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Unexpected server error |
Code Examples
@app.route('/users', methods=['POST'])
def create_user():
data = request.json
if not data or 'name' not in data:
return jsonify({"error": "Name is required"}), 400
try:
user = db.create_user(data)
# 201 Created with location header
response = jsonify(user.to_dict())
response.status_code = 201
response.headers['Location'] = f'/users/{user.id}'
return response
except IntegrityError:
return jsonify({"error": "User already exists"}), 409
@app.route('/users/<int:id>', methods=['DELETE'])
def delete_user(id):
user = db.get_user(id)
if not user:
return jsonify({"error": "User not found"}), 404
db.delete_user(id)
return '', 204 # No Content
app.get('/orders/:id', (req, res) => {
const order = db.findOrder(req.params.id);
if (!order) {
return res.status(404).json({ error: 'Order not found' });
}
if (order.visibility === 'private' && req.user.id !== order.userId) {
return res.status(403).json({ error: 'Access denied' });
}
res.status(200).json(order);
});
Common Mistakes
1. Always Returning 200
Every request gets 200 OK with error in body. Don't do this.
2. Using 400 for Auth Errors
Use 401 for auth issues, not 400.
3. No 201 with Location Header
POST responses should include Location header pointing to new resource.
4. 500 for Expected Errors
Client errors (validation, not found) should be 4xx, not 500.
5. 204 with Body
204 No Content means no body. Don't include one.
Practice Questions
- What status code for successful POST?
- What status code for successful DELETE?
- What is the difference between 401 and 403?
- What status code for rate limiting?
- What header should 201 include?
Answers:
- 201 Created.
- 204 No Content.
- 401 is unauthenticated; 403 is authenticated but not authorized.
- 429 Too Many Requests.
- Location header with the URL of the new resource.
Challenge: Audit your API endpoints. Ensure every endpoint returns the correct status code for each outcome (success, error, not found, conflict).
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro