Designing APIs that don't embarrass you in two years
·2 min read ·Backend · Architecture · REST APIs
APIs are contracts. Once clients depend on them, changing them is painful. A poorly designed API is a gift that keeps taking—every deprecation, every breaking change, every poorly named field that got shipped because it seemed fine at the time.
A few things I wish I'd gotten right from the start.
Version From Day One
/api/v1/users
/api/v1/orders
Even if you only have one version, the prefix lets you add /v2/ later without breaking existing clients. Without versioning, your first major change is a crisis.
Resources, Not Actions
REST is about resources, not operations. Name your endpoints after things, not verbs.
// Bad:
POST /api/createUser
POST /api/deleteUser?id=123
// Good:
POST /api/v1/users
DELETE /api/v1/users/123
HTTP already has verbs: GET, POST, PUT, PATCH, DELETE. Use them.
Consistent Error Responses
{
"message": "Validation failed",
"errors": {
"email": ["The email field is required."],
"name": ["The name must be at least 2 characters."]
}
}
Every error, everywhere in your API, should have the same shape. Clients shouldn't need to handle different error formats depending on which endpoint they called.
Pagination From the Start
Any endpoint that returns a list will eventually return too many records to fit in a response. Add pagination before you need it:
{
"data": [...],
"meta": { "total": 1432, "page": 1, "per_page": 15 }
}
Use Status Codes Correctly
200 for success. 201 for created. 400 for bad request. 401 for unauthenticated. 403 for unauthorized. 404 for not found. 422 for validation errors. 500 for your fault.
Don't return 200 with { "success": false } in the body. The HTTP layer exists for a reason.