REST API Design
December 9, 2024 |
permanent
- tags
- Architecture, API, REST
Singular or plural names for the resources #
The key principles are:
- Use consistent plural nouns for resource names
- Keep nesting shallow
- Use nouns not verbs (only as exceptions)
- Show clear resource relationships
GET /orders/ <---> orders
POST /orders/ <---> orders.push(data)
GET /orders/1/ <---> orders[1]
PUT /orders/1/ <---> orders[1] = data
GET /orders/1/lines/ <---> orders[1].lines
POST /orders/1/lines/ <---> orders[1].lines.push(data)
Resource and Sub-Resource best practices #
/resource/resource-id/sub-resources/
/resource/resource-id/sub-resources/sub-resource-id/
Why should we use this approach: #
/posts/:postId/comments/:commentId/
/users/:userName/articles/:articleId/
# over this one:
/comments/:commentId/
/articles/:articleId/
The main reason for this approach is readability;
- a nested resource URL can convey that one resource belongs to another one.
- It gives the appearance of a hierarchical relationship, like directories give in file-systems.
These URLs convey less meaning about the relationship: #
/books/:bookId/
/rating/:ratingId/
# Than these URLs:
/books/:bookId/
/books/:bookid/ratings/:ratingid/
We can directly see that the rating we are requesting belongs to a specific book. In many cases, this can make debugging easier.
Bad Examples of API Design #
Inconsistent pluralization: #
/user/123/ # singular
/orders/456/ # plural
Deep nesting beyond 2-3 levels: #
/users/123/posts/456/comments/789/likes/
Using verbs instead of nouns: #
/getUser/123/
/createOrder/
Non-hierarchical relationships: #
/comments/123/ # When it should be /posts/456/comments/123/
/ratings/789/ # When it should be /books/456/ratings/789/
Mixing plural/singular in the same API: #
/company/123/employee/ # inconsistent naming
/companies/123/employees/ # better
Incorrect usage of verbs #
Using verbs for resource naming:
/getUserDetails/ /updateOrderStatus/ /deleteProduct/These should be noun-based to reflect the resource being manipulated:
/users/:userId/ /orders/:orderId/ /products/:productId/Embedding actions within the URL:
/users/123/publishArticle/ /accounts/456/sendWelcomeEmail/Instead, use HTTP methods to represent actions:
POST /users/123/articles/ # To publish an article POST /accounts/456/welcome-email/ # To send a welcome email
When HTTP Verbs are not enough #
When the HTTP vers are not enough to capture the action on resources correctly
Key principles: #
- Use nouns for resources, verbs for actions
- Put
actions after resource identifier - Use
POST for actions that modify state - Query parameters for filtering/search
- Prefer sub-resources over custom endpoints when possible
For actions on REST resources, here are common patterns: #
# Search/autocomplete
GET /users/search/?q=term
GET /users/?search=term
# Custom actions using verbs
POST /orders/id/cancel/
POST /tickets/id/resolve/
POST /accounts/id/activate/
# Bulk operations
POST /users/bulk-delete/
POST /orders/batch-update/
# Processing/computations
POST /documents/id/process/
POST /invoices/id/calculate-tax/
POST /invoices/id/validate/
# File operations
POST /documents/id/convert/
POST /files/id/analyze/
Keep responses consistent:
"success": true,
"data": ...,
"message": "Order cancelled successfully"
Commonly used HTTP Verbs with brief reason #
Safe HTTP Verbs: #
- GET: Retrieve data from a resource. It doesn’t modify the resource (safe and idempotent).
- HEAD: Same as GET, but only retrieves headers (safe and idempotent).
- OPTIONS: Describe the communication options for the target resource (safe and idempotent).
Unsafe/Idempotent HTTP Verbs: #
- PUT: Update or create a resource at a specified URI. Repeated requests with the same data yield the same result (idempotent).
- DELETE: Remove a resource. If the resource is already gone, the result is still the same (idempotent).
Unsafe/Non-idempotent HTTP Verbs: #
- POST: Create a new subordinate resource or submit data. Subsequent identical requests may create new resources each time.
- PATCH: Partially update a resource. Patch operations may result in differing states with repeated requests if not handled carefully.