REST Lens
← Back to All Rules
Rule 6

GET Retrieve

Category: HTTP Methods

Description

Retrieval operations should use the HTTP GET method. Any endpoint whose path suggests data retrieval (containing keywords like get, retrieve, fetch, find, list, or search) must use GET, not POST, PUT, PATCH, or DELETE.

What It Checks

This rule validates that operations intended to retrieve data use the appropriate HTTP GET method. It checks:

  • Path segments containing retrieval keywords: get, retrieve, fetch, find, list, search
  • Ensures these operations use GET method exclusively
  • Flags violations when retrieval operations use POST, PUT, PATCH, or DELETE methods

The rule performs a keyword-based analysis of the path to identify retrieval intent, then verifies the HTTP method aligns with that intent.

Why It Matters

Using the correct HTTP method for retrieval operations is fundamental to RESTful API design:

  • Semantic Correctness: GET is defined by HTTP specification as the method for retrieving data without side effects
  • Caching: GET requests can be cached by browsers, CDNs, and proxies, improving performance
  • Safety: GET is a safe method that should not modify server state, making it safe to retry and prefetch
  • Idempotency: GET requests are idempotent and can be called multiple times without changing results
  • Browser Compatibility: Only GET requests can be easily bookmarked, linked, and navigated to directly
  • API Clarity: Correct method usage makes API behavior predictable and self-documenting

Examples

Good ✅

paths:
  /users:
    get:
      summary: List all users
      responses:
        '200':
          description: Array of users

  /users/{userId}:
    get:
      summary: Retrieve a specific user
      responses:
        '200':
          description: User object

  /products/search:
    get:
      summary: Search products
      parameters:
        - name: query
          in: query
          schema:
            type: string
      responses:
        '200':
          description: Search results

  /orders/find:
    get:
      summary: Find orders
      parameters:
        - name: status
          in: query
          schema:
            type: string
      responses:
        '200':
          description: Matching orders

  /reports/fetch:
    get:
      summary: Fetch report data
      responses:
        '200':
          description: Report data

Bad ❌

paths:
  /users/list:
    post:  # Should be GET - listing is a retrieval operation
      summary: List all users
      responses:
        '200':
          description: Array of users

  /users/{userId}/retrieve:
    post:  # Should be GET - retrieve is explicitly a read operation
      summary: Retrieve a specific user
      responses:
        '200':
          description: User object

  /products/search:
    post:  # Should be GET unless requires complex body parameters
      summary: Search products
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                query:
                  type: string
      responses:
        '200':
          description: Search results

  /orders/find:
    put:  # Should be GET - find is a retrieval operation
      summary: Find orders
      responses:
        '200':
          description: Matching orders

  /reports/get:
    delete:  # Should be GET - get is a retrieval keyword
      summary: Get report data
      responses:
        '200':
          description: Report data

Configuration

This rule has no configuration options. It is either enabled or disabled.

The keyword detection includes: get, retrieve, fetch, find, list, search (case-insensitive).

How to Fix

  1. Change the HTTP method to GET:

    # Before
    /users/list:
      post:
        summary: List users
    
    # After
    /users/list:
      get:
        summary: List users
    
  2. Move request body parameters to query parameters:

    # Before
    /search:
      post:
        requestBody:
          content:
            application/json:
              schema:
                properties:
                  query:
                    type: string
                  limit:
                    type: integer
    
    # After
    /search:
      get:
        parameters:
          - name: query
            in: query
            schema:
              type: string
          - name: limit
            in: query
            schema:
              type: integer
    
  3. For complex search/filter operations that truly need a request body (e.g., complex JSON structures), consider:

    • Using query parameters with structured formats (e.g., JSON strings)
    • Renaming the endpoint to not include retrieval keywords if it has side effects
    • Using POST with a different path that doesn't imply simple retrieval (e.g., /search-queries instead of /search)
    • Documenting why GET is not appropriate in this specific case
  4. Remove retrieval keywords from paths if the operation is not actually a retrieval:

    # If the operation has side effects
    /users/search:
      post:  # Violation
    
    # Rename to reflect the actual action
    /user-search-records:
      post:  # No violation - not using retrieval keywords
    

Related Rules

  • Rule 5: GET/POST Tunneling - Prevents misuse of GET and POST for other operations
  • Rule 7: POST Create - Ensures creation operations use POST method
  • Rule 3: CRUDy URIs - Prevents CRUD operation names in URI paths