One rule
Use versions for planned change. Use errors for clear recovery.
A teammate should know two things from every failed call: what went wrong, and what they can do next.
Version with the URL
For a hackathon API, put the version in the path: /api/v1. It is easy to see, easy to test in Postman or curl, and simple to document.
Start with v1. Do not create v2 until you make a breaking change, such as renaming fields, removing fields, or changing how a URL works.
Avoid fake versions
Do not add /v2 just because you changed internal code or database tables. If the request and response still work the same for users, keep it as v1.
Also avoid mixing styles like /api/v1/events and /api/events?version=1 in the same project. Pick one style and stay with it.
Create error rules
Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.
0 of 5 done
Error response shape
Use one shape across the API. This helps your frontend teammate handle errors without writing special code for every route.
Here is a simple format you can copy into your docs and backend.
{
"error": {
"code": "EVENT_NOT_FOUND",
"message": "No event found with id evt_123.",
"details": {
"id": "evt_123"
}
}
}Express example
This example shows versioned routes and one shared error handler. Keep the response format the same for validation errors, missing resources, and server errors.
If you use AI to generate this, ask it to add test requests too. Check that it does not return HTML error pages.
import express from "express";
const app = express();
app.use(express.json());
const events = [
{ id: "evt_1", title: "College Hack Night", city: "Pune" }
];
app.get("/api/v1/events/:id", (req, res, next) => {
const event = events.find(e => e.id === req.params.id);
if (!event) {
return res.status(404).json({
error: {
code: "EVENT_NOT_FOUND",
message: `No event found with id ${req.params.id}.`,
details: { id: req.params.id }
}
});
}
res.status(200).json({ data: event });
});
app.use((err, req, res, next) => {
console.error(err);
res.status(500).json({
error: {
code: "INTERNAL_ERROR",
message: "Something went wrong. Try again later."
}
});
});
app.listen(3000, () => console.log("API running on port 3000"));Use boring codes
Make error codes stable and readable: EVENT_NOT_FOUND, INVALID_PAGE, EMAIL_ALREADY_USED. Your message can change later, but the code should not break client logic.
For validation errors, add details per field. For example, title is required, price must be a number, or page must be at least 1.
Do this now
Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.
0 of 5 done