DEV Community

Gianfranco Coppola
Gianfranco Coppola

Posted on

Choosing the Right HTTP Method for Your REST API

✅ Choosing the Right HTTP Method for Your REST API

Introduction

When designing a REST API, choosing the right HTTP method is more than a convention—it’s a fundamental aspect of API design. The HTTP method you pick impacts the clarity, consistency, and maintainability of your API.

A well-designed API is easy to understand because developers can predict its behavior based on standard HTTP semantics. Misusing methods (e.g., using POST for everything) can lead to confusion, poor documentation, and even security risks.

In this article, we’ll explore:

  • ✅ The most common HTTP methods
  • ✅ When to use each
  • ✅ Key concepts like idempotence and safety
  • ✅ Practical examples using Spring Boot
  • ✅ Real-world tips (file uploads, logical deletes)

Overview of HTTP Methods

The HTTP specification defines several methods, but in REST APIs, the most common are:

  • GET: Retrieve data from the server.
  • POST: Create a new resource on the server.
  • PUT: Update or replace an existing resource.
  • PATCH: Partially update an existing resource.
  • DELETE: Remove a resource from the server.

Each method has a specific purpose and semantic meaning defined by the HTTP/1.1 specification (RFC 7231). Let’s see how to use them correctly.


🔍 Why Choosing the Right Method Matters

Using the proper HTTP method:

  • Improves clarity for API consumers
  • Aligns your API with RESTful best practices
  • Ensures compatibility with HTTP caching, proxies, and tools
  • Helps with SEO and API discoverability when exposed as OpenAPI/Swagger

🔑 Common HTTP Methods and When to Use Them

GET

  • Purpose: Retrieve resources without modifying them.
  • Characteristics:
    • Safe: Does not change server state.
    • Idempotent: Multiple identical requests return the same result.
  • Response: 200 OK
  • Example use case: Get a list of products or retrieve a specific product.
  GET /api/products
  GET /api/products/{id}
Enter fullscreen mode Exit fullscreen mode

🛠 Spring Boot Example

@GetMapping("/api/products")
    public ResponseEntity<List<Product>> getAllProducts() {
        List<Product> products = productService.getAllProducts();
        return ResponseEntity.ok(products);
    }
Enter fullscreen mode Exit fullscreen mode

POST

  • Purpose: Create a new resource or start an action that modifies state.
  • Characteristics:
    • Not Idempotent: Calling multiple times creates multiple resources or triggers the action repeatedly.
  • Response: 201 Created
  • Example use case:

    • Add a new product
    • Upload a file for processing (e.g., importing a CSV)
    • Trigger a background job
    POST /api/products
    

    Request Body:

    {
      "name": "Updated Laptop",
      "price": 1099.99,
      "categoryId": 2
    }
    

🛠 Spring Boot Example

// Create a new product
@PostMapping("/api/products")
    public ResponseEntity<Product> createProduct(@RequestBody Product productRequest) {
        Product product = productService.createProduct(productRequest);
        return ResponseEntity.status(HttpStatus.CREATED).body(product);
    }

// Upload a file for processing
@PostMapping("/import")
public ResponseEntity<String> importProducts(@RequestParam("file") MultipartFile file) {
    productService.importFromFile(file);
    return ResponseEntity.accepted().body("Import started");
}
Enter fullscreen mode Exit fullscreen mode

🔍 Notice the use of 202 Accepted:

  • This status code is perfect when the request is accepted but the processing will occur asynchronously (e.g., background job, file import).
  • The client can later check the status of the operation via another endpoint (polling) or with a callback mechanism.

PUT

  • Purpose: Replace the entire resource with a new one.
  • Characteristics:
    • Idempotent: Multiple identical requests result in the same state.
  • Response: 200 OK or 204 No Content
  • Example use case: Update all details of a product.

    PUT /api/products/10
    

    Request Body:

    {
      "name": "Updated Laptop",
      "price": 1099.99,
      "categoryId": 2
    }
    

🛠 Spring Boot Example

@PutMapping("/api/products/{id}")
    public ResponseEntity<Product> updateProduct(
            @PathVariable Long id,
            @RequestBody Product request) {
        Product product = productService.updateProduct(id, request);
        return ResponseEntity.ok(product);
    }
Enter fullscreen mode Exit fullscreen mode

PATCH

  • Purpose: Partially update a resource (modify only specific fields)
  • Characteristics:
    • Not necessarily Idempotent: Depends on implementation.
  • Response: 200 OK or 204 No Content
  • Example use case: Update only the price of a product.

    PATCH /api/products/10
    

    Request Body:

    {
      "price": 899.99
    }
    

🛠 Spring Boot Example

@PatchMapping("/api/products/{id}")
    public ResponseEntity<Product> updateProduct(
            @PathVariable Long id,
            @RequestBody Map<String, Object> updates) {
        Product product = productService.partialUpdate(id, updates);
        return ResponseEntity.ok(product);
    }
Enter fullscreen mode Exit fullscreen mode

DELETE

  • Purpose: Delete an existing resource.
  • Characteristics:
    • Idempotent: Deleting the same resource multiple times has the same effect.
  • Response: 204 No Content
  • Example use case: Delete a product.
  DELETE /api/products/10
Enter fullscreen mode Exit fullscreen mode

🛠 Spring Boot Example

@DeleteMapping("/api/products/{id}")
    public ResponseEntity<Void> deleteProduct(@PathVariable Long id) {
        productService.deleteProduct(id);
        return ResponseEntity.noContent().build();
    }
Enter fullscreen mode Exit fullscreen mode

🔍 What About Logical Deletion?

In some systems, we don't actually remove the record from the database, but mark it as deleted (soft delete).

You have two common options:

  1. Use DELETE but implement it as logical deletion internally (recommended for API clarity).
  2. Use PATCH with a status field, e.g., { "status": "INACTIVE" }.

🛠 Spring Boot Example

@DeleteMapping("api/products/{id}")
public void softDeleteProduct(@PathVariable Long id) {
    productService.markAsDeleted(id); // Sets deleted flag instead of removing
}
Enter fullscreen mode Exit fullscreen mode

📌 Idempotence and Safety Explained

Two important concepts in HTTP semantics:

  • Safety: A method is safe if it does not change the server state.
    • Safe methods: GET, HEAD.
  • Idempotence: A method is idempotent if multiple identical requests have the same effect as a single request.
    • Idempotent methods: GET, PUT, DELETE.

Why does this matter?
Understanding these concepts helps you design APIs that behave predictably and handle retries without side effects.

Concept Meaning Example
Safe No state changes GET
Idempotent Same result after multiple identical calls PUT, DELETE

✅ Summary Table

HTTP Method Action Idempotent Safe
GET Read ✅ Yes ✅ Yes
POST Create ❌ No ❌ No
PUT Replace ✅ Yes ❌ No
PATCH Update ✅ Yes* ❌ No
DELETE Delete ✅ Yes ❌ No

*PATCH is generally idempotent if the same patch is applied multiple times.


⚠️ Common Mistakes to Avoid

  • ❌ Using GET to create or update resources
  • ❌ Using POST for all operations
  • ❌ Returning 200 OK for resource creation (should be 201 Created)

✅ Best Practices for HTTP Methods

  • Use GET for retrieval
  • Use POST for creation
  • Use PUT for full update
  • Use PATCH for partial update
  • Use DELETE for deletion
  • Do not abuse POST: Use POST only for creating resources or triggering processes, not for updates or deletions.
  • Be consistent: Always use methods according to their semantics.
  • Avoid custom verbs: Stick to standard HTTP methods instead of inventing new ones like /users/disable.
  • Handle status codes properly:
    • 200 OK → Successful GET or update.
    • 201 Created → Resource successfully created.
    • 202 Accepted → Request accepted for asynchronous processing (e.g., file import, background job).
    • 204 No Content → Successful DELETE or update with no response body.
    • 400 Bad Request → Client sent invalid data.
    • 404 Not Found → Resource not found.

🔗 Conclusion and Related Resources

Choosing the right HTTP method is crucial for building clean, predictable, and RESTful APIs. Stick to standard semantics, respect idempotence and safety, and your API will be easier to understand and maintain.

Want more? Check out the GitHub repository for more examples and full implementations and my Pro Starter Kit on Gumroad.


Top comments (0)