
If you’ve ever written an API where everything returns 200 OK, I’ve got bad news: your frontend devs are quietly cursing your name.
HTTP already gives you a rich set of status codes. Use them properly, and your API becomes way easier to debug, maintain, and work with.
Rule #1: Use the Right Status Code for the Job
Here’s your status code starter pack:
| Code | Use When |
|---|---|
| 200 | Request was successful |
| 201 | Resource created (after POST) |
| 204 | No content to return (DELETE, etc) |
| 400 | Bad request (client messed up) |
| 401 | Unauthorized (missing/invalid auth) |
| 403 | Forbidden (valid auth, no access) |
| 404 | Resource not found |
| 409 | Conflict (e.g., duplicate entries) |
| 500 | Server error (you messed up) |
Example: Using Real Status Codes (TypeScript + Express)
app.post('/users', (req, res) => {
const { name } = req.body;
if (!name) {
return res.status(400).json({
error: {
code: 'NAME_REQUIRED',
message: 'Name field is required.'
}
});
}
const user = createUser(name);
res.status(201).json(user);
});This tells the frontend exactly what went wrong — and uses the proper 201 Created when things go right.
Rule #2: Structure Your Errors
Your error responses should be as consistent as your success responses.
Recommended format:
{
"error": {
"code": "RESOURCE_NOT_FOUND",
"message": "The requested user does not exist."
}
}✔️ Easy to parse
✔️ Friendly for internationalization
✔️ Works great with logs and metrics
Example: Standardized 404 Response
app.get('/users/:id', (req, res) => {
const user = findUserById(req.params.id);
if (!user) {
return res.status(404).json({
error: {
code: 'USER_NOT_FOUND',
message: `No user found with ID ${req.params.id}`
}
});
}
res.json(user);
});Rule #3: Handle Query Parameters with Grace
For filtering, sorting, and pagination, always use query params — but make sure to validate them.
Example:
GET /posts?author=alex&sort=latest&page=2&pageSize=10app.get('/posts', (req, res) => {
const { author, sort = 'newest', page = 1, pageSize = 10 } = req.query;
const posts = getFilteredPosts({ author, sort, page, pageSize });
res.json(posts);
});🔧 Use default values
🔒 Sanitize inputs
🧼 Keep responses consistent
Recap
- Use status codes like you mean it — don’t abuse 200
- Error responses should be structured, not chaos in JSON form
- Query params are your friends — just keep them clean and validated
Coming Up Next:
Part 4: “REST API Pro Tips: Headers, HATEOAS, and When to Break the Rules”
We’ll dig into headers, how much REST is too much REST, and where you can break the rules like a pro.