-
Verb in URL path "getUsers" uses an action word. REST URLs should represent resources (nouns), not actions. The HTTP method already communicates the action.
-
Camel case naming "getUsers" mixes casing styles. REST convention mandates lowercase, hyphen-separated paths (kebab-case) for readability and consistency.
-
No versioning There is no API version prefix (e.g.,
/v1/). Without versioning, future breaking changes cannot be introduced safely. -
No pagination support Fetching all users without query params like
?page=1&limit=20will cause performance issues at scale and is not REST-idiomatic.
❌ Original
GET /getUsers
Verb in path, camelCase, no version, no pagination.
✅ Corrected
GET /v1/users
GET /v1/users?page=1&limit=20
Noun resource, lowercase, versioned, pagination-ready.
| Code | Meaning | When to use |
|---|---|---|
| 200 OK | Success | Users list returned successfully |
| 400 Bad Request | Invalid query params | e.g., ?page=-1 or non-numeric limit |
| 401 Unauthorized | Not authenticated | Missing or invalid auth token |
| 403 Forbidden | Not authorized | Authenticated but lacks permission |
| 500 Internal Server Error | Server failure | Unexpected database or server error |
GET /v1/users?page=1&limit=20 HTTP/1.1 Host: api.example.com Authorization: Bearer eyJhbGci... Accept: application/json
{
"data": [
{ "id": 1, "name": "Alice", "email": "[email protected]" },
{ "id": 2, "name": "Bob", "email": "[email protected]" }
],
"pagination": {
"page": 1,
"limit": 20,
"total": 142,
"totalPages": 8
}
}
-
Wrong HTTP method (POST instead of DELETE) POST is for creating resources. Deleting a resource must use the
DELETEmethod, which is semantically correct and allows caches/proxies to behave properly. -
Verb "delete" in the URL path The action "delete" is already expressed by the HTTP method. Embedding it in the URL is redundant and violates REST's resource-oriented architecture.
-
Singular resource name "user" REST convention uses plural nouns for collections (
/users). Singular forms create inconsistency across the API surface. -
No versioning prefix Same issue as endpoint 1 — missing
/v1/makes future evolution risky.
❌ Original
POST /user/delete/5
Wrong method, verb in path, singular noun, no version.
✅ Corrected
DELETE /v1/users/5
Correct DELETE method, noun-only path, plural, versioned.
| Code | Meaning | When to use |
|---|---|---|
| 204 No Content | Deleted successfully | Resource deleted; no body needed in response |
| 200 OK | Deleted with body | If you return the deleted resource in the response |
| 401 Unauthorized | Not authenticated | Missing or invalid auth token |
| 403 Forbidden | Not authorized | Cannot delete another user's account without admin |
| 404 Not Found | User doesn't exist | ID 5 does not exist in the database |
| 500 Internal Server Error | Server failure | Unexpected error during deletion |
DELETE /v1/users/5 HTTP/1.1 Host: api.example.com Authorization: Bearer eyJhbGci...
HTTP/1.1 204 No Content Content-Length: 0 // No response body — deletion was successful
{
"error": {
"code": 404,
"message": "User with ID 5 not found",
"path": "/v1/users/5"
}
}
-
Wrong HTTP method (GET instead of POST) GET is a safe, idempotent method for reading data. Creating a resource must use POST. Using GET to mutate state violates HTTP semantics — GET requests can be cached, bookmarked, or pre-fetched, causing unintended duplicate user creation.
-
Sensitive data in query string Query parameters are logged in server access logs, browser history, and proxy caches. User data (name, email, password) must be sent in the request body, not the URL.
-
Verb "createUser" in URL Same anti-pattern — actions belong in HTTP methods, not URL paths. The URL should be the resource (
/users), the method (POST) implies creation. -
CamelCase URL "createUser" violates kebab-case convention. All paths should be lowercase.
-
No versioning prefix Missing
/v1/API version prefix.
❌ Original
GET /createUser?name=Jo
Wrong method, data in URL, verb in path, camelCase, no version.
✅ Corrected
POST /v1/users
Data in JSON body, POST for creation, noun path, versioned.
| Code | Meaning | When to use |
|---|---|---|
| 201 Created | Resource created | User successfully created; include Location header |
| 400 Bad Request | Validation error | Missing required fields, invalid email format, etc. |
| 401 Unauthorized | Not authenticated | Missing or invalid auth token |
| 409 Conflict | Duplicate resource | User with that email already exists |
| 422 Unprocessable Entity | Semantic validation fail | Data is well-formed but fails business rules |
| 500 Internal Server Error | Server failure | Unexpected error during creation |
POST /v1/users HTTP/1.1 Host: api.example.com Authorization: Bearer eyJhbGci... Content-Type: application/json { "name": "Jo Smith", "email": "[email protected]", "password": "s3cur3P@ss!", "role": "user" }
HTTP/1.1 201 Created Location: /v1/users/143 { "id": 143, "name": "Jo Smith", "email": "[email protected]", "role": "user", "createdAt": "2024-01-15T10:30:00Z" }
-
Verb "update" in URL path "updateAllUsers" is an action, not a resource. PUT already communicates the update intent. The URL should identify what is being updated.
-
CamelCase URL "updateAllUsers" violates REST naming conventions. Paths must be lowercase, using hyphens for word separation where needed.
-
PUT is wrong for partial bulk updates — use PATCH PUT implies a full replacement of the resource. If you're updating specific fields across users, PATCH is semantically correct. PUT on a collection would mean replacing the entire collection.
-
Dangerous bulk operation with no scoping Allowing unrestricted bulk updates on all users is a major security and reliability risk. Bulk operations must be explicit, scoped, and ideally require elevated permissions.
-
No versioning prefix Missing
/v1/API version prefix.
❌ Original
PUT /updateAllUsers
Verb in path, camelCase, wrong method for partial update, dangerous, no version.
✅ Corrected (single user)
PATCH /v1/users/{id}
PUT /v1/users/{id}
PATCH for partial update, PUT for full replace, scoped to one user.
ℹ️ If bulk update is truly needed
PATCH /v1/users/bulk
Use a dedicated bulk sub-resource. Require explicit IDs in body. Add admin-only auth scope. Log all changes.
PUT vs PATCH
PUT — full replacement. Must send the complete resource. Missing fields may be set to null/default.
PATCH — partial update. Only send the fields you want to change.
| Code | Meaning | When to use |
|---|---|---|
| 200 OK | Updated successfully | Return updated resource in response body |
| 204 No Content | Updated, no body | Update successful, no need to return body |
| 400 Bad Request | Validation error | Invalid field values in request body |
| 401 Unauthorized | Not authenticated | Missing or invalid auth token |
| 403 Forbidden | Not authorized | Trying to update another user without admin role |
| 404 Not Found | User not found | Specified user ID doesn't exist |
| 409 Conflict | Conflict | e.g., email already in use by another account |
| 500 Internal Server Error | Server failure | Unexpected error during update |
PATCH /v1/users/5 HTTP/1.1 Host: api.example.com Authorization: Bearer eyJhbGci... Content-Type: application/json { "name": "Jo Updated Smith" }
PUT /v1/users/5 HTTP/1.1 Content-Type: application/json { "name": "Jo Updated Smith", "email": "[email protected]", "role": "admin" }
{
"id": 5,
"name": "Jo Updated Smith",
"email": "[email protected]",
"role": "admin",
"updatedAt": "2024-01-15T11:00:00Z"
}
Returns a paginated list of users. Supports filtering and sorting via query parameters.
| Query Param | Type | Description |
|---|---|---|
page | integer | Page number (default: 1) |
limit | integer | Results per page (default: 20, max: 100) |
sort | string | Field to sort by, e.g., name, createdAt |
order | string | asc or desc |
search | string | Search by name or email |
Returns a single user resource. Returns 404 if the user does not exist.
GET /v1/users/42 → 200 OK | 404 Not Found
Creates a new user. Data sent in JSON body. Returns 201 with Location header pointing to the new resource.
POST /v1/users → 201 Created | 400 | 409 Conflict
Updates only the provided fields on a user. Use PUT for full replacement.
PATCH /v1/users/5 → 200 OK | 404 Not Found | 409 Conflict
Completely replaces a user resource. All required fields must be provided. Missing optional fields will be reset to defaults.
PUT /v1/users/5 → 200 OK | 400 Bad Request | 404 Not Found
Permanently deletes a user. Returns 204 No Content on success. Operation is idempotent.
DELETE /v1/users/5 → 204 No Content | 404 Not Found
Read/retrieve a resource or collection. Never modifies state.
✓ Safe & IdempotentCreate a new resource. Response includes Location header.
✗ Not IdempotentFull replacement of a resource. Must send complete representation.
✓ IdempotentPartial update. Only send fields that need changing.
~ Context-dependentRemove a resource permanently. Returns 204 on success.
✓ IdempotentResources, Not Actions
URLs identify things (nouns). HTTP methods express what to do with them. Never put verbs like "get", "create", "delete" in paths.
Consistent Naming
Use lowercase, plural nouns, and kebab-case for multi-word paths. Example: /user-profiles not /UserProfiles.
Proper Status Codes
Use semantically correct HTTP status codes. 201 for creation, 204 for no-content deletions, 404 when not found.
Data in Body, Not URL
Sensitive or complex data belongs in the request body, not query strings. URLs are logged and cached by proxies and browsers.
API Versioning
Always prefix with /v1/. This allows breaking changes to be introduced in /v2/ without disrupting existing clients.