Design Issues Found
12
Issues Resolved
12
Endpoints Audited
4
Status Codes Defined
10
📐 Core REST Principles Applied
🔤
Nouns, not verbsURLs identify resources; HTTP methods express actions.
🔡
Lowercase & hyphensUse
/user-profiles, never camelCase or underscores.
📦
Plural collections
/users for a collection, /users/5 for a member.
🔀
Correct HTTP verbsGET=read, POST=create, PUT/PATCH=update, DELETE=delete.
🚦
Meaningful status codes201 Created, 204 No Content, 400 Bad Request, etc.
🔒
No sensitive data in URLUse request body or headers for sensitive params.
🔄 Endpoint-by-Endpoint Analysis
1
GET
/getUsers
List all users
▼
❌ Original
GET/getUsers
✅ Corrected
GET/users
⚠ Issues Identified
- Verb in URL path —
getUsersembeds the action as a verb. REST URLs must represent resources (nouns), not actions. The HTTP method (GET) already communicates the action. - Non-plural resource name — Collections should use the plural form:
/usersnot/user. - Action-based naming — Naming routes after CRUD operations (
get,create,delete) couples the URL to implementation details and breaks discoverability.
✅ Fixes Applied
- Removed the
getverb — the HTTPGETmethod already expresses retrieval. - Renamed to plural
/usersto represent the collection resource. - Optional query parameters such as
?page=1&limit=20&sort=namecan be appended for pagination and filtering.
🚦 Expected Status Codes
200 OK — users array returned
401 Unauthorized — missing auth
403 Forbidden — insufficient permissions
500 Internal Server Error
2
POST
/user/delete/5
Delete user #5
▼
❌ Original
POST/user/delete/5
✅ Corrected
DELETE/users/5
⚠ Issues Identified
- Wrong HTTP method — Using
POSTto delete a resource is semantically incorrect.DELETEis the designated method for resource removal and is idempotent by specification. - Verb in URL path —
/deleteshould never appear in a REST path. TheDELETEHTTP method communicates this intent. - Singular resource name —
/usershould be/users(plural collection), with the ID identifying the specific member. - Non-idempotent semantics —
POSTis not idempotent; calling it multiple times can produce different results.DELETEis idempotent — deleting an already-deleted resource returns 404 gracefully.
✅ Fixes Applied
- Changed method to
DELETE— semantically correct and idempotent. - Removed
/deletesegment from the path entirely. - Changed
/user→/usersfor consistent plural collection naming. - Resource identifier
/5remains as the path parameter targeting the specific user.
🚦 Expected Status Codes
204 No Content — deleted successfully
404 Not Found — user doesn't exist
401 Unauthorized
403 Forbidden
3
GET
/createUser?name=Jo
Create a user
▼
❌ Original
GET/createUser?name=Jo
✅ Corrected
POST/users
Body:
{"name":"Jo","email":"..."}⚠ Issues Identified
- GET used for a state-changing operation —
GETmust be safe (read-only, no side effects). Creating a resource is a side effect and must usePOST. - Sensitive/payload data in the query string — Query strings are stored in server logs, browser history, and proxy caches. User data (name, email, password) must travel in the request body over HTTPS.
- Verb in URL path —
createUsermixes action + resource. The correct pattern isPOST /users— POST to the collection. - Caching hazard — GET requests are cacheable by default. A cached "create user" request could silently replay, causing duplicate records.
✅ Fixes Applied
- Changed method to
POST— the correct verb for creating a new resource in a collection. - Moved all user data to the JSON request body, keeping it out of URLs and logs.
- URL simplified to
/users— POSTing to the collection is the standard REST creation pattern. - Response should include a
Locationheader pointing to the newly created resource, e.g.Location: /users/42.
🚦 Expected Status Codes
201 Created — new user created
400 Bad Request — invalid/missing fields
409 Conflict — email already exists
422 Unprocessable Entity — validation error
4
PUT
/updateAllUsers
Bulk update users
▼
❌ Original
PUT/updateAllUsers
✅ Corrected (options)
PATCH/users — bulk partial update
PUT/users/5 — full replace single user
⚠ Issues Identified
- Verb in URL path —
updateis an action; it belongs in the HTTP method, not the URL. - Ambiguous scope — "All" is dangerous — Bulk operations must be explicit and intentional. A single endpoint silently modifying every user record is an extreme data-integrity risk with no scoping mechanism.
- Wrong semantics for partial updates —
PUTimplies a full replacement of the resource. If only some fields change,PATCHis the correct method and communicates partial update intent clearly. - camelCase path — REST paths should be
lowercase-with-hyphens.updateAllUsersuses camelCase which is inconsistent and not URL-friendly.
✅ Fixes Applied
- Removed
updateverb — the HTTP method conveys this. - For updating a single user:
PUT /users/{id}(full replace) orPATCH /users/{id}(partial update). - For bulk updates:
PATCH /userswith a JSON body array is acceptable, but should require explicit IDs in the payload — never an implicit "all". - Consider adding a filter query parameter for scoped bulk updates:
PATCH /users?role=admin.
🚦 Expected Status Codes
200 OK — updated, returns updated resource(s)
204 No Content — updated, no body returned
400 Bad Request — malformed body
404 Not Found — user ID not found
📊 Quick-Reference: Before vs After
| # | Original Endpoint | Corrected Endpoint | Primary Issues | Success Code |
|---|---|---|---|---|
| 1 | GET /getUsers | GET /users | Verb in URL, singular name | 200 OK |
| 2 | POST /user/delete/5 | DELETE /users/5 | Wrong method, verb in URL, singular | 204 No Content |
| 3 | GET /createUser?name=Jo | POST /users | GET for mutation, data in URL, verb in path | 201 Created |
| 4 | PUT /updateAllUsers | PATCH /users/{id} | Verb in URL, wrong method, unsafe bulk op | 200 OK |
📚 REST Best-Practices Reference
🔤 URL Design Rules
- Use nouns, never verbs in paths
- Plural names for collections (
/users) - Lowercase letters and hyphens only
- Hierarchical nesting:
/users/5/posts - No trailing slashes
- No file extensions (
.json)
🔀 HTTP Method Semantics
- GET — Read, safe, idempotent, cacheable
- POST — Create, not idempotent
- PUT — Full replace, idempotent
- PATCH — Partial update, idempotent
- DELETE — Remove, idempotent
- HEAD / OPTIONS — Metadata / CORS
🚦 Status Code Cheat Sheet
- 200 OK — general success
- 201 Created — resource created
- 204 No Content — success, no body
- 400 Bad Request — client error
- 401 Unauthorized — auth required
- 403 Forbidden — auth insufficient
- 404 Not Found — resource missing
- 409 Conflict — state conflict
- 422 Unprocessable — validation fail
- 500 Internal Server Error
🔒 Security Considerations
- Never put sensitive data in query strings
- Always use HTTPS in production
- Use Authorization headers for tokens
- Validate and sanitize all inputs
- Rate-limit write endpoints
- Require explicit scoping for bulk ops
📦 Request / Response Patterns
- Return
Locationheader on 201 - Use JSON consistently (
Content-Type) - Wrap collections:
{"data":[], "meta":{}} - Include pagination metadata
- Use consistent error object shape
- Support
If-Matchfor optimistic locking
🔢 Versioning Strategies
- URL prefix:
/v1/users(most common) - Header:
Accept: application/vnd.api+json;v=1 - Query param:
/users?version=1 - Never break existing contracts
- Deprecate with sunset headers
- Document all versions clearly