Category: HTTP Methods
Description
POST endpoints that toggle binary state (e.g., star/unstar, follow/unfollow, mute/unmute) should be split into separate PUT (to set) and DELETE (to unset) operations for idempotent, predictable behavior.
What It Checks
This rule analyzes POST operations in the API:
- Only considers POST endpoints where the same path lacks both PUT and DELETE methods
- Uses AI to determine if the operation toggles between two states
- Flags toggle operations that should be split into explicit set/unset endpoints
Why It Matters
Splitting toggles into PUT + DELETE improves:
- Idempotency: PUT and DELETE are idempotent by definition — clients can safely retry without unexpected state changes
- Predictability: Callers know exactly what state they're setting, rather than hoping the toggle lands on the right side
- Race Conditions: With a toggle, two concurrent calls cancel each other out; with PUT/DELETE, concurrent calls converge to the intended state
- Client Simplicity: No need to first GET the current state before toggling — just PUT to set or DELETE to unset
Examples
Good
paths:
/repos/{id}/star:
put:
operationId: starRepo
summary: Star a repository
responses:
"204":
description: Repository starred
delete:
operationId: unstarRepo
summary: Unstar a repository
responses:
"204":
description: Repository unstarred
/users/{id}/follow:
put:
operationId: followUser
summary: Follow a user
responses:
"204":
description: User followed
delete:
operationId: unfollowUser
summary: Unfollow a user
responses:
"204":
description: User unfollowed
Bad
paths:
/repos/{id}/star:
post:
operationId: toggleStar
summary: Toggle star on a repository
# Toggles state — not idempotent, not predictable
responses:
"200":
description: Star toggled
/users/{id}/follow:
post:
operationId: toggleFollow
summary: Toggle follow status
# Callers can't express intent — "set" vs "unset"
responses:
"200":
description: Follow toggled
Exceptions
- APIs where the toggle is intentionally atomic and the client always reads the new state from the response
- Internal APIs with controlled concurrency where race conditions are not a concern
Configuration
This rule has no configuration options. It is either enabled or disabled.
Related Rules
- Rule 5: GET/POST Tunneling - Detect misuse of GET/POST for other operations
- Rule 82: Idempotent Design - POST should not be used for idempotent operations