REST Lens
← Back to All Rules
Rule 7

POST for Create

Category: HTTP Methods

Description

POST requests should be used for creating new resources, not GET or other methods.

What It Checks

This rule validates that resource creation operations use the POST HTTP method:

  • Detects endpoints with "create" semantics
  • Checks that they use POST (not GET, PUT, or others)
  • Ensures proper REST method usage

Why It Matters

Using POST for creation is a core REST principle:

  • Idempotency: POST is non-idempotent, matching create semantics
  • HTTP standards: POST is defined for creating subordinate resources
  • Client expectations: Developers expect POST for creation
  • Caching: GET requests may be cached, inappropriate for mutations

Examples

Good ✅

paths:
  /users:
    post:  # ✅ Correct method for creation
      summary: Create a new user
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                email:
                  type: string
      responses:
        '201':
          description: User created successfully

  /orders:
    post:  # ✅ POST for creating orders
      summary: Create an order
      responses:
        '201':
          description: Order created

Bad ❌

paths:
  /users/create:
    get:  # ❌ Using GET for creation
      summary: Create a new user
      parameters:
        - name: name
          in: query
        - name: email
          in: query
      responses:
        '200':
          description: User created

  /users:
    put:  # ❌ PUT should be for updates
      summary: Create a user
      requestBody:
        required: true
      responses:
        '200':
          description: Created

HTTP Method Semantics

MethodPurposeIdempotentUse Case
POSTCreate new resourceNoCreating a new user, order, etc.
PUTReplace entire resourceYesUpdating all fields of a resource
PATCHPartial updateNoUpdating specific fields
GETRetrieve resourceYesReading data (never for creation!)
DELETERemove resourceYesDeleting a resource

Common Violations

1. GET for Create

# Bad - GET should never create resources
GET /users/create?name=John&[email protected]

# Good
POST /users
Content-Type: application/json
{
  "name": "John",
  "email": "[email protected]"
}

2. PUT for Create (without known ID)

# Bad - PUT requires knowing the full URI
PUT /users
{ "name": "John" }

# Good - POST lets server assign ID
POST /users
{ "name": "John" }
# Returns: Location: /users/12345

When to Use PUT vs POST

POST (for create)

  • Server assigns resource ID
  • Client doesn't know final URI
  • Creating subordinate resources
POST /articles
{ "title": "New Article" }
→ Returns 201 with Location: /articles/789

PUT (for upsert with known ID)

  • Client specifies exact URI
  • Replaces entire resource
  • Idempotent operation
PUT /articles/specific-slug
{ "title": "Article", "content": "..." }
→ Creates or replaces the article at this exact URI

Configuration

This rule has no configuration options.

How to Fix

  1. Change GET to POST for creation:

    # Before
    GET /users/create?name=John
    
    # After
    POST /users
    Body: { "name": "John" }
    
  2. Use POST instead of PUT for new resources:

    # Before
    PUT /orders  # Creating new order
    
    # After
    POST /orders
    
  3. Return 201 Created with Location header:

    responses:
      '201':
        description: Resource created
        headers:
          Location:
            schema:
              type: string
            example: /users/12345
    

Best Practices

  1. Return 201 Created: Not 200 OK
  2. Include Location header: URI of the newly created resource
  3. Return the created resource: In the response body
  4. Use request body: Not query parameters for creation data
POST /users
Content-Type: application/json
{ "name": "Alice", "email": "[email protected]" }

Response:
201 Created
Location: /users/67890
Content-Type: application/json
{
  "id": "67890",
  "name": "Alice",
  "email": "[email protected]",
  "createdAt": "2025-12-22T10:30:00Z"
}

Related Rules

  • Rule 34: Code 201 Create - Response status code for creation
  • Rule 19: Location on Create - Location header requirement
  • Rule 5: GET/POST Tunneling - Preventing GET misuse