Designing Resource URIs

1. Using Nouns for Resources

URIs identify resources (nouns), not actions (verbs). Use HTTP methods for verbs.

Anti-PatternRESTful
GET /getUsersGET /users
POST /createUserPOST /users
POST /deleteUser/42DELETE /users/42
POST /updateUserEmailPATCH /users/42

2. Using Plural Nouns

Resource TypeConventionExample
CollectionPlural noun/orders, /users
Single ItemPlural + ID/orders/100
SingletonSingular noun/users/42/profile (only one)

3. Structuring Hierarchical Resources

PatternExampleMeaning
Parent/Child/users/42/ordersAll orders for user 42
Grandchild/users/42/orders/100/itemsItems in order 100
Max Depth2-3 levelsDeeper → flatten with query params
Note: Avoid > 3 levels of nesting. Use /items?orderId=100&userId=42 instead.

4. Using Lowercase and Hyphens

BadGoodReason
/UserProfile/user-profilesURIs case-sensitive; lowercase universal
/user_profiles/user-profilesHyphens better for SEO & readability
/userProfiles/user-profilescamelCase reserved for body fields

5. Avoiding File Extensions

BadGoodUse Instead
/users/42.json/users/42Accept: application/json header
/users/42.xml/users/42Accept: application/xml header

6. Designing Collection vs Singleton Resources

TypeURI PatternOperations
Collection/ordersGET (list), POST (create)
Item/orders/{id}GET, PUT, PATCH, DELETE
Singleton/users/{id}/profileGET, PUT, PATCH (no POST/DELETE)

7. Handling Nested Resources

Example: Nested Resource Endpoints

GET    /users/42/orders          # List user's orders
POST   /users/42/orders          # Create order for user
GET    /users/42/orders/100      # Specific order
DELETE /users/42/orders/100      # Cancel user's order

# Alternative (flat) - preferred when child has independent identity
GET    /orders?userId=42
GET    /orders/100
When to NestWhen to Flatten
Child has no meaning without parentChild has independent identity
Strong containment (1:N)Cross-cutting queries needed

8. Using Resource Identifiers

ID TypeExampleProsCons
Integer/users/42Compact, sortableEnumerable, leaks count
UUID/users/550e8400-e29b-...Unguessable, distributed-safeLong, not human-friendly
Slug/articles/intro-to-restSEO-friendly, readableMutable, collision risk
ULID/NanoID/orders/01ARZ3NDEK...Sortable + unguessableNewer, less tooling

9. Designing Action-Based Endpoints

Some operations don't fit CRUD. Use sub-resources or controller endpoints sparingly.

ActionRESTful Approach
Send emailPOST /users/42/emails (create email resource)
Cancel orderPOST /orders/100/cancel or PATCH /orders/100 {"status":"cancelled"}
SearchGET /users/search?q=john or GET /users?q=john
LoginPOST /sessions or POST /auth/login
Bulk importPOST /users/import

10. Handling Special Characters in URIs

CharacterEncodedUse
(space)%20 or + (query)Always encode
/%2FIf part of ID, not separator
?%3FIn path segments
#%23Always (fragment delimiter)
&%26In query values
UnicodeUTF-8 → percent-encodee.g. caf%C3%A9

11. Using Query Parameters

PurposeExample
Filter?status=active&role=admin
Sort?sort=-createdAt,name
Paginate?page=2&limit=20
Field Select?fields=id,name,email
Expand?expand=author,comments
Search?q=john
Note: Path = identification, Query = modification. Never use query params to identify resources.