Design Problems Identified
8 violations found across 4 endpoints
REST URLs must identify resources (nouns), not actions (verbs).
The word get is redundant — the HTTP method GET already
communicates the intent. Including verbs like getUsers, createUser,
or deleteUser in the path is an RPC-style anti-pattern.
GET /users
POST is semantically incorrect for deletion. HTTP defines
DELETE specifically for removing resources. Using POST
for destructive operations hides intent, breaks idempotency expectations,
and prevents HTTP caches/proxies from behaving correctly.
DELETE /users/5
GET requests must be safe and idempotent — they must
not cause side effects. Creating a resource is a side effect. Using GET
to create data means web crawlers, browser prefetchers, and caches could accidentally
create users. Additionally, createUser is a verb in the URL.
POST /users with JSON body
Passing user data (name, email, password) as query parameters exposes it in
server logs, browser history, referrer headers, and network monitoring tools.
Resource creation payloads must travel in the request body
with Content-Type: application/json.
The endpoints mix singular (/user/) and plural (/users)
resource names. REST convention mandates plural nouns for
collection endpoints (/users) for consistency and predictability.
A single user is then /users/{id}.
/users and /users/{'{id}'}
The path segment /delete/ is an action verb embedded in the URL.
The HTTP method DELETE already expresses this intent. The URL
should only identify the resource: /users/5. The method tells
the server what to do with it.
DELETE /users/5
PUT /updateAllUsers has two issues: a verb in the URL, and
PUT implies a complete replacement of a single resource.
Bulk updates should use PATCH /users (partial update on the collection)
with filtering/body constraints, and must require explicit confirmation to avoid
accidental mass data changes.
PATCH /users with request body filters
URL paths should use lowercase kebab-case
(e.g., /user-profiles), not camelCase. URLs are
case-sensitive on most servers; camelCase leads to inconsistency and
hard-to-type paths. RFC 3986 and industry convention both recommend
lowercase with hyphens as separators.
/users, /users/{'{id}'}Before & After Comparison
Original vs corrected endpoint mapping
| ❌ Original (Broken) | ✅ Corrected (REST) | Issues Fixed | |
|---|---|---|---|
| GET /getUsers | → | GET /users | Verb removed Plural noun |
| POST /user/delete/5 | → | DELETE /users/5 | Correct method Verb removed Plural noun |
| GET /createUser?name=Jo | → | POST /users | Correct method Verb removed Body payload |
| PUT /updateAllUsers | → | PATCH /users | Correct method Verb removed Bulk PATCH |
Corrected API Endpoints
Full reference with parameters, request bodies, and response examples
Returns a paginated collection of user objects. Supports filtering by status
and sorting. This replaces the original broken GET /getUsers.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| page | integer | optional | Page number (default: 1) |
| limit | integer | optional | Items per page (default: 20) |
| status | string | optional | Filter: active | inactive |
Response Status Codes
GET /users?page=1&limit=20&status=active Authorization: Bearer <token> Accept: application/json
{
"status": "success",
"data": {
"users": [
{
"id": 1,
"name": "Alice Johnson",
"email": "[email protected]",
"status": "active",
"created_at": "2024-01-15T10:30:00Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 142,
"total_pages": 8
}
}
}
Returns a single user resource identified by their unique integer ID. This endpoint is safe and idempotent.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | integer | required | Unique user identifier |
Response Status Codes
{
"status": "success",
"data": {
"user": {
"id": 5,
"name": "Bob Smith",
"email": "[email protected]",
"status": "active",
"role": "editor",
"created_at": "2024-02-20T08:00:00Z",
"updated_at": "2024-06-01T14:22:00Z"
}
}
}
Creates a new user resource. Data is sent in the JSON request body
— never in query parameters. Returns 201 Created with a
Location header pointing to the new resource.
Replaces the broken GET /createUser?name=Jo.
Request Body Fields
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | required | Full name (min 2 chars) |
| string | required | Valid email address | |
| password | string | required | Min 8 chars |
| role | string | optional | viewer | editor | admin |
Response Status Codes
{
"name": "Jo Williams",
"email": "[email protected]",
"password": "Secur3P@ss!",
"role": "editor"
}
// Headers Location: /users/143 Content-Type: application/json // Body { "status": "success", "message": "User created successfully", "data": { "user": { "id": 143, "name": "Jo Williams", "email": "[email protected]", "role": "editor", "created_at": "2024-07-10T12:00:00Z" } } }
Complete replacement of a user resource. All fields must be
provided. Missing fields will be set to null/default. Use PATCH
for partial updates. This is idempotent — repeated calls
produce the same result.
Path Parameters
| Name | Type | Required |
|---|---|---|
| id | integer | required |
Response Status Codes
{
"name": "Jo Williams",
"email": "[email protected]",
"role": "admin",
"status": "active"
}
Updates only the fields provided in the request body. Unspecified fields
remain unchanged. Preferred over PUT for most update operations.
{
"status": "inactive"
// Only this field will be updated
}
Response Status Codes
Performs a partial update on multiple users matching a filter.
Requires explicit confirmation via the X-Confirm-Bulk: true header
to prevent accidental mass changes. Replaces the broken PUT /updateAllUsers.
Required Headers
| Header | Value | Purpose |
|---|---|---|
| X-Confirm-Bulk | true | Safety guard for bulk ops |
Response Status Codes
PATCH /users X-Confirm-Bulk: true Content-Type: application/json { "filter": { "status": "active" }, "update": { "role": "viewer" } }
{
"status": "success",
"data": {
"matched": 89,
"updated": 89
},
"message":