Introduction
A well-designed REST API URL structure is crucial for building scalable, readable, and maintainable APIs. In this blog, we will break down the components of a REST API URL, discuss best practices, and implement them in Spring Boot with a complete example.
1. General REST API URL Structure
A standard REST API URL follows this pattern:
https://api.example.com/{version}/{resource}/{resource-id}/{sub-resource}
Breakdown:
-
https://
→ Secure protocol (HTTPS is preferred) -
api.example.com
→ Domain name or API host -
{version}
→ API versioning (e.g.,v1
,v2
) -
{resource}
→ Plural noun representing the resource (e.g.,users
,products
) -
{resource-id}
→ Unique identifier for a resource (e.g.,users/123
) -
{sub-resource}
→ Nested resource related to the main resource (e.g.,users/123/orders
)
2. Components of REST API URL
A. Versioning in REST API
Versioning ensures backward compatibility and can be implemented in different ways:
- URL Path Versioning (Recommended)
https://api.example.com/v1/users
- Header Versioning
GET /users
Accept: application/vnd.example.v1+json
- Query Parameter Versioning
GET /users?version=1
B. Resource Naming (Use Plural Nouns)
Always use plural nouns for resources:
GET /v1/users → Get all users
GET /v1/users/123 → Get user with ID 123
POST /v1/users → Create a new user
PUT /v1/users/123 → Update user 123
DELETE /v1/users/123 → Delete user 123
C. Sub-Resources for Relationships
Use sub-resources to represent relationships:
GET /v1/users/123/orders → Get orders of user 123
GET /v1/users/123/orders/456 → Get order 456 of user 123
D. Query Parameters for Filtering, Sorting, and Pagination
Filtering:
GET /v1/products?category=electronics&brand=apple
Sorting:
GET /v1/products?sort=price_asc
Pagination:
GET /v1/products?page=2&limit=20
Offset-based Pagination:
GET /v1/products?offset=40&limit=20
E. Actions that Don’t Fit CRUD (Use Verbs as Subpaths)
For actions beyond CRUD, use verbs:
POST /v1/users/123/activate → Activate user 123
POST /v1/orders/789/cancel → Cancel order 789
F. Status and Error Handling
Use appropriate HTTP status codes:
-
200 OK
→ Successful request -
201 Created
→ Resource created -
400 Bad Request
→ Client error -
404 Not Found
→ Resource not found -
500 Internal Server Error
→ Server issue
3. Best Practices for REST API URL Design
✅ Use nouns for resources (/users
instead of /getUsers
)
✅ Use hyphens (-) instead of underscores (_) in URLs (/user-profiles
not /user_profiles
)
✅ Use lowercase letters (/orders
instead of /Orders
)
✅ Avoid file extensions (/users.json
is unnecessary)
✅ Keep URLs short and intuitive
4. Spring Boot Implementation
Let's implement these best practices in a Spring Boot REST API for managing users and orders.
A. User Controller with Versioning, Pagination, Filtering, Offset-based Pagination, and Sorting
@RestController
@RequestMapping("/v1/users")
public class UserController {
@Autowired
private UserRepository userRepository;
@GetMapping
public ResponseEntity<List<User>> getAllUsers(
@RequestParam(required = false) String name,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(defaultValue = "id") String sortBy,
@RequestParam(defaultValue = "asc") String sortDir,
@RequestParam(required = false) Integer offset) {
Sort sort = sortDir.equalsIgnoreCase("desc") ? Sort.by(sortBy).descending() : Sort.by(sortBy).ascending();
Pageable pageable = offset != null ? PageRequest.of(offset / size, size, sort) : PageRequest.of(page, size, sort);
Page<User> users;
if (name != null) {
users = userRepository.findByNameContaining(name, pageable);
} else {
users = userRepository.findAll(pageable);
}
return ResponseEntity.ok(users.getContent());
}
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
return userRepository.findById(id)
.map(ResponseEntity::ok)
.orElseGet(() -> ResponseEntity.notFound().build());
}
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
return ResponseEntity.status(HttpStatus.CREATED).body(userRepository.save(user));
}
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User updatedUser) {
return userRepository.findById(id).map(user -> {
user.setName(updatedUser.getName());
user.setEmail(updatedUser.getEmail());
return ResponseEntity.ok(userRepository.save(user));
}).orElseGet(() -> ResponseEntity.notFound().build());
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userRepository.deleteById(id);
return ResponseEntity.noContent().build();
}
}
Conclusion
Designing a RESTful API URL properly improves usability, scalability, and maintainability. By following best practices and implementing them in Spring Boot, you can build high-quality, developer-friendly APIs with versioning, pagination, offset-based pagination, sorting, and filtering.
Would you like to extend this with authentication or advanced query capabilities? Let me know in the comments! 🚀
Top comments (0)