🔍 REST API Design Review

User Management System — Endpoint Audit & Correction Guide

4 Problematic Endpoints 14 Design Issues Found 4 Corrected Endpoints
📊 Audit Summary
4
Bad Endpoints
14
Issues Found
4
Fixed Endpoints
5
HTTP Methods Used
🚨 Problematic Endpoints
GET /getUsers Retrieve all users
  • 🔴
    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=20 will 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.

CodeMeaningWhen to use
200 OKSuccessUsers list returned successfully
400 Bad RequestInvalid query paramse.g., ?page=-1 or non-numeric limit
401 UnauthorizedNot authenticatedMissing or invalid auth token
403 ForbiddenNot authorizedAuthenticated but lacks permission
500 Internal Server ErrorServer failureUnexpected database or server error
Request
GET /v1/users?page=1&limit=20 HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGci...
Accept: application/json
Response — 200 OK
{
  "data": [
    { "id": 1, "name": "Alice", "email": "[email protected]" },
    { "id": 2, "name": "Bob",   "email": "[email protected]"   }
  ],
  "pagination": {
    "page":       1,
    "limit":      20,
    "total":      142,
    "totalPages": 8
  }
}
POST /user/delete/5 Delete a user by ID
  • 🔴
    Wrong HTTP method (POST instead of DELETE) POST is for creating resources. Deleting a resource must use the DELETE method, 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.

CodeMeaningWhen to use
204 No ContentDeleted successfullyResource deleted; no body needed in response
200 OKDeleted with bodyIf you return the deleted resource in the response
401 UnauthorizedNot authenticatedMissing or invalid auth token
403 ForbiddenNot authorizedCannot delete another user's account without admin
404 Not FoundUser doesn't existID 5 does not exist in the database
500 Internal Server ErrorServer failureUnexpected error during deletion
Request
DELETE /v1/users/5 HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGci...
Response — 204 No Content
HTTP/1.1 204 No Content
Content-Length: 0

// No response body — deletion was successful
Response — 404 Not Found
{
  "error": {
    "code":    404,
    "message": "User with ID 5 not found",
    "path":    "/v1/users/5"
  }
}
GET /createUser?name=Jo Create a new user
  • 🔴
    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.

CodeMeaningWhen to use
201 CreatedResource createdUser successfully created; include Location header
400 Bad RequestValidation errorMissing required fields, invalid email format, etc.
401 UnauthorizedNot authenticatedMissing or invalid auth token
409 ConflictDuplicate resourceUser with that email already exists
422 Unprocessable EntitySemantic validation failData is well-formed but fails business rules
500 Internal Server ErrorServer failureUnexpected error during creation
Request
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"
}
Response — 201 Created
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"
}
PUT /updateAllUsers Update all users (bulk)
  • 🔴
    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.

CodeMeaningWhen to use
200 OKUpdated successfullyReturn updated resource in response body
204 No ContentUpdated, no bodyUpdate successful, no need to return body
400 Bad RequestValidation errorInvalid field values in request body
401 UnauthorizedNot authenticatedMissing or invalid auth token
403 ForbiddenNot authorizedTrying to update another user without admin role
404 Not FoundUser not foundSpecified user ID doesn't exist
409 ConflictConflicte.g., email already in use by another account
500 Internal Server ErrorServer failureUnexpected error during update
PATCH Request — Partial Update
PATCH /v1/users/5 HTTP/1.1
Host:         api.example.com
Authorization: Bearer eyJhbGci...
Content-Type:  application/json

{
  "name": "Jo Updated Smith"
}
PUT Request — Full Replacement
PUT /v1/users/5 HTTP/1.1
Content-Type: application/json

{
  "name":  "Jo Updated Smith",
  "email": "[email protected]",
  "role":  "admin"
}
Response — 200 OK
{
  "id":        5,
  "name":      "Jo Updated Smith",
  "email":     "[email protected]",
  "role":      "admin",
  "updatedAt": "2024-01-15T11:00:00Z"
}
✅ Corrected API — Full Reference
GET /v1/users List all users (paginated)

Returns a paginated list of users. Supports filtering and sorting via query parameters.

Query ParamTypeDescription
pageintegerPage number (default: 1)
limitintegerResults per page (default: 20, max: 100)
sortstringField to sort by, e.g., name, createdAt
orderstringasc or desc
searchstringSearch by name or email
GET /v1/users/{id} Get a single user by ID

Returns a single user resource. Returns 404 if the user does not exist.

Example
GET /v1/users/42200 OK | 404 Not Found
POST /v1/users Create a new user

Creates a new user. Data sent in JSON body. Returns 201 with Location header pointing to the new resource.

Example
POST /v1/users201 Created | 400 | 409 Conflict
PATCH /v1/users/{id} Partially update a user

Updates only the provided fields on a user. Use PUT for full replacement.

Example
PATCH /v1/users/5200 OK | 404 Not Found | 409 Conflict
PUT /v1/users/{id} Fully replace a user

Completely replaces a user resource. All required fields must be provided. Missing optional fields will be reset to defaults.

Example
PUT /v1/users/5200 OK | 400 Bad Request | 404 Not Found
DELETE /v1/users/{id} Delete a user by ID

Permanently deletes a user. Returns 204 No Content on success. Operation is idempotent.

Example
DELETE /v1/users/5204 No Content | 404 Not Found
📖 HTTP Method Quick Reference
GET

Read/retrieve a resource or collection. Never modifies state.

✓ Safe & Idempotent
POST

Create a new resource. Response includes Location header.

✗ Not Idempotent
PUT

Full replacement of a resource. Must send complete representation.

✓ Idempotent
PATCH

Partial update. Only send fields that need changing.

~ Context-dependent
DELETE

Remove a resource permanently. Returns 204 on success.

✓ Idempotent
🏛️ REST Design Principles
📦

Resources, 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.